openapi: 3.1.0
info:
  title: SES Platform - Mailbox API
  description: "# Mailbox API (System)\n\nPublic API for sending and receiving emails.\
    \ Designed for programmatic access by\nAI agents and automated systems.\n\n##\
    \ Authentication\nAll endpoints (except health checks) require HMAC-SHA256 authentication.\n\
    \n### Required Headers\n| Header | Description |\n|--------|-------------|\n|\
    \ `X-API-Key` | Your API key ID (e.g., `MK-ACME-ABCD1234`) |\n| `X-Timestamp`\
    \ | Unix timestamp in seconds |\n| `X-Body-Hash` | SHA256 hash of request body\
    \ (base64-encoded) |\n| `X-Signature` | HMAC-SHA256 signature (hex-encoded) |\n\
    \n### Signature Generation\n\nThe signature is computed over: `METHOD\\nPATH\\\
    nCANONICAL_QUERY\\nBODY_HASH\\nTIMESTAMP`\n\n- **CANONICAL_QUERY**: Query parameters\
    \ sorted by key (then value), percent-encoded per RFC 3986, joined with `&`. Empty\
    \ string if no query params.\n\n```python\nimport base64\nimport hashlib\nimport\
    \ hmac\nimport time\nfrom urllib.parse import parse_qsl, quote\n\ndef generate_auth_headers(api_key_id:\
    \ str, api_secret: str, method: str, path: str, body: str = \"\", query: str =\
    \ \"\") -> dict:\n    timestamp = str(int(time.time()))\n    body_hash = base64.b64encode(hashlib.sha256(body.encode()).digest()).decode()\n\
    \n    # Canonicalize query string: parse, percent-encode, sort by key (then value),\
    \ rejoin\n    if query:\n        query = query.lstrip(\"?\")  # Remove leading\
    \ ? if present\n        params = parse_qsl(query, keep_blank_values=True)\n  \
    \      # Percent-encode keys and values, sort by (key, value)\n        encoded_params\
    \ = [(quote(k, safe=\"\"), quote(v, safe=\"\")) for k, v in params]\n        encoded_params.sort(key=lambda\
    \ x: (x[0], x[1]))\n        canonical_query = \"&\".join(f\"{k}={v}\" for k, v\
    \ in encoded_params)\n    else:\n        canonical_query = \"\"\n\n    string_to_sign\
    \ = f\"{method}\\n{path}\\n{canonical_query}\\n{body_hash}\\n{timestamp}\"\n\n\
    \    signature = hmac.new(\n        api_secret.encode(),\n        string_to_sign.encode(),\n\
    \        hashlib.sha256\n    ).hexdigest()\n\n    return {\n        \"X-API-Key\"\
    : api_key_id,\n        \"X-Timestamp\": timestamp,\n        \"X-Body-Hash\": body_hash,\n\
    \        \"X-Signature\": signature\n    }\n\n# Example: GET request with query\
    \ params\nheaders = generate_auth_headers(\n    api_key_id=\"MK-ACME-ABCD1234\"\
    ,\n    api_secret=\"your-secret-key\",  # pragma: allowlist secret\n    method=\"\
    GET\",\n    path=\"/api/v1/mailboxes/inbox/messages\",\n    query=\"limit=10&offset=0\"\
    \n)\n\n# Example: POST request without query params\nheaders = generate_auth_headers(\n\
    \    api_key_id=\"MK-ACME-ABCD1234\",\n    api_secret=\"your-secret-key\",  #\
    \ pragma: allowlist secret\n    method=\"POST\",\n    path=\"/api/v1/mailboxes/inbox/send\"\
    ,\n    body='{\"to\": [\"user@example.com\"], \"subject\": \"Hello\"}'\n)\n```\n\
    \n### Permission Levels\n| Permission | Capabilities |\n|------------|-------------|\n\
    | `sending_only` | Send emails only |\n| `receiving_only` | Read messages, view\
    \ analytics |\n| `admin` | Full access including credential management |\n\n##\
    \ Base Path\nAll routes are prefixed with `/api/v1/system`\n"
  version: 1.0.0
  contact:
    name: API Support
    url: https://agentmailbox.to/apidocs/
servers:
- url: https://api.agentmailbox.to
  description: Production
tags:
- name: attachments
  description: Email attachment handling
- name: domains
  description: Domain management and DNS verification
- name: email
  description: Email sending operations
- name: mailboxes
  description: Mailbox CRUD operations
- name: messages
  description: Email message retrieval and management
- name: system
  description: System utilities and health checks
- name: tenants
  description: Tenant management operations
- name: usage
  description: Usage tracking and quotas
paths:
  /api/v1/system/attachments/upload-url:
    post:
      operationId: createSystemAttachmentsUploadUrl
      summary: Create Presigned Upload Url
      tags:
      - attachments
      security:
      - hmacSignature: []
      description: Requires 'sending' permission
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: Request body
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: 'Scan pending


            **When this occurs:** The attachment is still being scanned for malware.
            Retry the request after a few seconds.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Malware scan not yet completed
                error_id: 550e8400-e29b-41d4-a716-446655440000
                scan_status: pending
                retry_after: 5 seconds
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: &id001
                error: Authentication required
                error_id: 550e8400-e29b-41d4-a716-446655440000
                code: AUTHENTICATION_REQUIRED
                message: Valid API credentials are required for this endpoint.
                hint: Include valid HMAC signature headers.
                support_url: https://agentmailbox.to/support
        '403':
          description: Error 403
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: &id002
                error: Access denied
                error_id: 550e8400-e29b-41d4-a716-446655440000
                code: ACCESS_DENIED
                message: You do not have permission to access this resource.
                hint: Verify you have the correct permissions for this operation.
                support_url: https://agentmailbox.to/support
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: &id003
                error: Resource not found or access denied
                error_id: 550e8400-e29b-41d4-a716-446655440000
                code: NOT_FOUND
                hint: Verify the resource ID is correct and you have access to it.
                support_url: https://agentmailbox.to/support
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: &id004
                error: Failed to process request
                error_id: 550e8400-e29b-41d4-a716-446655440000
                message: An error occurred while processing your request. Please contact
                  support with the error ID if this persists.
                support_url: https://agentmailbox.to/support
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/attachments/upload-urls-batch:
    post:
      operationId: createSystemAttachmentsUploadUrlsBatch
      summary: Create Presigned Upload Urls Batch
      tags:
      - attachments
      security:
      - hmacSignature: []
      description: Requires 'sending' permission
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: Request body
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: 'Scan pending


            **When this occurs:** The attachment is still being scanned for malware.
            Retry the request after a few seconds.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Malware scan not yet completed
                error_id: 550e8400-e29b-41d4-a716-446655440000
                scan_status: pending
                retry_after: 5 seconds
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: Error 403
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id002
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id003
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/domains/{domain_name}:
    get:
      operationId: getSystemDomains
      summary: Get Domain Info
      tags:
      - domains
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: domain_name
        in: path
        required: true
        schema:
          type: string
        description: Full domain name (e.g., 'acme.agentmailbox.to')
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Domain'
              example:
                id: 2ef739e0-dedb-49ef-beb9-86fa70d1b133
                tenant_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                tenant_codename: acme
                full_domain: acme.agentmailbox.to
                subdomain: acme
                parent_domain: agentmailbox.to
                verification_status: verified
                dkim_status: verified
                sending_enabled: true
                receiving_enabled: true
                ses_identity_arn: arn:aws:ses:eu-west-2:123456789012:identity/acme.agentmailbox.to
                mailboxes:
                - id: 9f0e6e8e-5bf4-43f2-b7e7-53dfdd3a12a1
                  username: support
                  display_name: Support Team
                  email_address: support@acme.agentmailbox.to
                - id: 3a4b5c6d-7e8f-4a9b-8c1d-2e3f4a5b6c7d
                  username: sales
                  display_name: Sales Team
                  email_address: sales@acme.agentmailbox.to
                created_at: '2026-03-04T10:30:00Z'
                updated_at: '2026-03-04T10:35:00Z'
        '400':
          description: Error 400
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: &id005
                error: Invalid request format
                error_id: 550e8400-e29b-41d4-a716-446655440000
                code: VALIDATION_ERROR
                hint: Check the request body and query parameters for validation errors.
                support_url: https://agentmailbox.to/support
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: Error 403
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id002
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Domain not found
                error_id: 550e8400-e29b-41d4-a716-446655440000
                code: DOMAIN_NOT_FOUND
                hint: Verify the domain name is correct and the domain exists.
                support_url: https://agentmailbox.to/support
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/domains/{domain_name}/dns:
    get:
      operationId: listSystemDomainsDns
      summary: Get Domain Dns Status
      tags:
      - domains
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: domain_name
        in: path
        required: true
        schema:
          type: string
        description: Full domain name (e.g., 'acme.agentmailbox.to')
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
          minimum: 0
        description: Number of items to skip for pagination
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 250
        description: Maximum number of items to return
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DnsStatus'
              example:
                domain: acme.agentmailbox.to
                verification_status: verified
                dkim_status: verified
                spf_status: verified
                dmarc_status: verified
                required_records:
                - type: CNAME
                  name: _dkim1.acme.agentmailbox.to
                  value: dkim1.amazonses.com
                  status: verified
                  verified_at: '2026-03-04T10:35:00Z'
                - type: CNAME
                  name: _dkim2.acme.agentmailbox.to
                  value: dkim2.amazonses.com
                  status: verified
                  verified_at: '2026-03-04T10:35:00Z'
                - type: CNAME
                  name: _dkim3.acme.agentmailbox.to
                  value: dkim3.amazonses.com
                  status: verified
                  verified_at: '2026-03-04T10:35:00Z'
                sending_enabled: true
                receiving_enabled: true
                ai_explanation: All DNS records are properly configured. Your domain
                  is fully verified and ready for sending and receiving emails.
        '400':
          description: Error 400
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id005
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: Error 403
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id002
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id003
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/health:
    get:
      operationId: listSystemHealth
      summary: Health check endpoint
      tags:
      - system
      security:
      - hmacSignature: []
      parameters:
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
          minimum: 0
        description: Number of items to skip for pagination
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 250
        description: Maximum number of items to return
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                    - healthy
                  timestamp:
                    type: string
                    format: date-time
        '400':
          description: Error 400
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id005
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: Error 403
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id002
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id003
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/mailboxes:
    get:
      operationId: listSystemMailboxes
      summary: List Mailboxes
      tags:
      - mailboxes
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
          minimum: 0
        description: Number of items to skip for pagination
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 250
        description: Maximum number of items to return
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MailboxList'
              example: &id008
                mailboxes:
                - id: 9f0e6e8e-5bf4-43f2-b7e7-53dfdd3a12a1
                  domain_id: 2ef739e0-dedb-49ef-beb9-86fa70d1b133
                  username: support
                  display_name: Support Team
                  email_address: support@acme.agentmailbox.to
                  created_at: '2026-03-04T10:30:00Z'
                - id: 3a4b5c6d-7e8f-4a9b-8c1d-2e3f4a5b6c7d
                  domain_id: 2ef739e0-dedb-49ef-beb9-86fa70d1b133
                  username: sales
                  display_name: Sales Team
                  email_address: sales@acme.agentmailbox.to
                  created_at: '2026-03-04T10:30:00Z'
                pagination:
                  count: 2
                  limit: 50
                  offset: 0
        '400':
          description: Error 400
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id005
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'No accessible tenants


            **When this occurs:** The credential has no tenant associations and cannot
            access mailbox data.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: No accessible tenants
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id003
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/mailboxes/messages:
    get:
      operationId: listSystemMailboxesMessages
      summary: List Mailbox Messages
      tags:
      - mailboxes
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
          minimum: 0
        description: Number of items to skip for pagination
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 250
        description: Maximum number of items to return
      - name: is_read
        in: query
        schema:
          type: boolean
        description: Filter by read status
      - name: since
        in: query
        schema:
          type: string
          format: date-time
        description: Filter messages after this timestamp (ISO 8601)
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageList'
              example: &id009
                messages:
                - id: 8b3f9c5e-f7f7-4fd2-91fa-187f20c3da36
                  mailbox_id: 9f0e6e8e-5bf4-43f2-b7e7-53dfdd3a12a1
                  message_id: <msg123@acme.agentmailbox.to>
                  thread_id: b7c8d9e0-1234-4567-89ab-cdef12345678
                  direction: inbound
                  from_address: customer@example.com
                  to_addresses:
                  - support@acme.agentmailbox.to
                  subject: Question about my order
                  timestamp: '2026-03-04T10:30:00Z'
                  is_read: false
                  is_archived: false
                  has_attachments: false
                total: 1
                limit: 10
                offset: 0
        '400':
          description: 'Missing required parameter


            **When this occurs:** The mailbox_id was not provided in the request.
            Either scope the credential to a mailbox or provide mailbox_id in the
            request.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Missing required parameter
                error_id: 550e8400-e29b-41d4-a716-446655440000
                field: mailbox_id
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'Mailbox access denied


            **When this occurs:** Mailbox-scoped credential is attempting to access
            messages from a different mailbox.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Mailbox access denied
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: 'Message not found


            **When this occurs:** The requested message ID does not exist in the database
            or has been deleted.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Message not found
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/mailboxes/messages/{message_id}:
    get:
      operationId: getSystemMailboxesMessages
      summary: Get Mailbox Message
      tags:
      - mailboxes
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: message_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: UUID of the message
      - name: is_read
        in: query
        schema:
          type: boolean
        description: Filter by read status
      - name: since
        in: query
        schema:
          type: string
          format: date-time
        description: Filter messages after this timestamp (ISO 8601)
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
              example:
                id: 8b3f9c5e-f7f7-4fd2-91fa-187f20c3da36
                mailbox_id: 9f0e6e8e-5bf4-43f2-b7e7-53dfdd3a12a1
                message_id: <msg123@acme.agentmailbox.to>
                thread_id: b7c8d9e0-1234-4567-89ab-cdef12345678
                direction: inbound
                from_address: customer@example.com
                to_addresses:
                - support@acme.agentmailbox.to
                cc_addresses: []
                subject: Question about my order
                body_text: 'Hi, I have a question about order #12345...'
                body_html: <p>Hi, I have a question about order <strong>#12345</strong>...</p>
                timestamp: '2026-03-04T10:30:00Z'
                is_read: true
                is_archived: false
                has_attachments: true
                attachments:
                - id: c8d9e0f1-2345-4678-9abc-def123456789
                  filename: receipt.pdf
                  content_type: application/pdf
                  size_bytes: 45678
                  download_url: https://api.agentmailbox.to/attachments/c8d9e0f1-2345.../download
        '400':
          description: 'Missing required parameter


            **When this occurs:** The mailbox_id was not provided in the request.
            Either scope the credential to a mailbox or provide mailbox_id in the
            request.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Missing required parameter
                error_id: 550e8400-e29b-41d4-a716-446655440000
                field: mailbox_id
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'Mailbox access denied


            **When this occurs:** Mailbox-scoped credential is attempting to access
            messages from a different mailbox.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Mailbox access denied
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: 'Message not found


            **When this occurs:** The requested message ID does not exist in the database
            or has been deleted.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Message not found
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
    patch:
      operationId: updateSystemMailboxesMessages
      summary: Update Mailbox Message Flags
      tags:
      - mailboxes
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: message_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: UUID of the message
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                is_read:
                  type: boolean
                is_archived:
                  type: boolean
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
              example:
                id: 8b3f9c5e-f7f7-4fd2-91fa-187f20c3da36
                is_read: true
                is_archived: false
                updated_at: '2026-03-04T10:35:00Z'
        '400':
          description: 'Missing update fields


            **When this occurs:** Update request must include at least one of: is_read,
            is_archived. No fields to update were provided.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Missing update fields
                error_id: 550e8400-e29b-41d4-a716-446655440000
                message: At least one of is_read or is_archived must be provided
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'Unauthorized message update


            **When this occurs:** Credential does not have access to this message''s
            tenant.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Unauthorized message update
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: 'Message not found


            **When this occurs:** The requested message ID does not exist.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Message not found
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      operationId: deleteSystemMailboxesMessages
      summary: Delete Mailbox Message
      tags:
      - mailboxes
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: message_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: UUID of the message
      responses:
        '400':
          description: Error 400
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id005
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'No accessible tenants


            **When this occurs:** The credential has no tenant associations and cannot
            access mailbox data.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: No accessible tenants
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id003
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '204':
          description: Resource deleted successfully
  /api/v1/system/mailboxes/messages/{message_id}/attachments/{attachment_id}:
    get:
      operationId: getSystemMailboxesMessagesAttachments
      summary: Get Inbound Attachment
      tags:
      - mailboxes
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: message_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: UUID of the message
      - name: attachment_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: UUID of the attachment
      - name: is_read
        in: query
        schema:
          type: boolean
        description: Filter by read status
      - name: since
        in: query
        schema:
          type: string
          format: date-time
        description: Filter messages after this timestamp (ISO 8601)
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AttachmentDownload'
              example:
                id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                filename: document.pdf
                content_type: application/pdf
                size_bytes: 125430
                download_url: https://attachments.agentmailbox.to/signed/...
                expires_at: '2026-03-21T04:00:00Z'
        '400':
          description: 'Missing required parameter


            **When this occurs:** The mailbox_id was not provided in the request.
            Either scope the credential to a mailbox or provide mailbox_id in the
            request.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Missing required parameter
                error_id: 550e8400-e29b-41d4-a716-446655440000
                field: mailbox_id
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'Mailbox access denied


            **When this occurs:** Mailbox-scoped credential is attempting to access
            messages from a different mailbox.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Mailbox access denied
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: 'Message not found


            **When this occurs:** The requested message ID does not exist in the database
            or has been deleted.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Message not found
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/mailboxes/sent:
    get:
      operationId: listSystemMailboxesSent
      summary: List Sent Messages
      tags:
      - mailboxes
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
          minimum: 0
        description: Number of items to skip for pagination
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 250
        description: Maximum number of items to return
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageList'
              example:
                messages:
                - id: 8b3f9c5e-f7f7-4fd2-91fa-187f20c3da36
                  mailbox_id: 9f0e6e8e-5bf4-43f2-b7e7-53dfdd3a12a1
                  message_id: <msg123@acme.agentmailbox.to>
                  direction: outbound
                  from_address: support@acme.agentmailbox.to
                  to_addresses:
                  - customer@example.com
                  subject: 'Re: Your inquiry'
                  body_preview: Thank you for contacting us...
                  created_at: '2026-03-04T11:30:00Z'
                pagination:
                  count: 1
                  limit: 50
                  offset: 0
        '400':
          description: Error 400
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id005
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'No accessible tenants


            **When this occurs:** The credential has no tenant associations and cannot
            access mailbox data.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: No accessible tenants
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id003
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/mailboxes/sent/{message_id}:
    get:
      operationId: getSystemMailboxesSent
      summary: Get Sent Message
      tags:
      - mailboxes
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: message_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: UUID of the message
      - name: is_read
        in: query
        schema:
          type: boolean
        description: Filter by read status
      - name: since
        in: query
        schema:
          type: string
          format: date-time
        description: Filter messages after this timestamp (ISO 8601)
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
              example:
                id: 8b3f9c5e-f7f7-4fd2-91fa-187f20c3da36
                mailbox_id: 9f0e6e8e-5bf4-43f2-b7e7-53dfdd3a12a1
                message_id: <msg123@acme.agentmailbox.to>
                direction: outbound
                from_address: support@acme.agentmailbox.to
                to_addresses:
                - customer@example.com
                subject: 'Re: Your inquiry'
                body_text: Thank you for contacting us. We will respond shortly.
                created_at: '2026-03-04T11:30:00Z'
        '400':
          description: 'Missing required parameter


            **When this occurs:** The mailbox_id was not provided in the request.
            Either scope the credential to a mailbox or provide mailbox_id in the
            request.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Missing required parameter
                error_id: 550e8400-e29b-41d4-a716-446655440000
                field: mailbox_id
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'Mailbox access denied


            **When this occurs:** Mailbox-scoped credential is attempting to access
            messages from a different mailbox.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Mailbox access denied
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: 'Message not found


            **When this occurs:** The requested message ID does not exist in the database
            or has been deleted.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Message not found
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/mailboxes/sent/{message_id}/attachments/{attachment_id}:
    get:
      operationId: getSystemMailboxesSentAttachments
      summary: Get Sent Attachment
      tags:
      - mailboxes
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: message_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: UUID of the message
      - name: attachment_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: UUID of the attachment
      - name: is_read
        in: query
        schema:
          type: boolean
        description: Filter by read status
      - name: since
        in: query
        schema:
          type: string
          format: date-time
        description: Filter messages after this timestamp (ISO 8601)
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AttachmentDownload'
              example:
                id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                filename: invoice.pdf
                content_type: application/pdf
                size_bytes: 125430
                download_url: https://attachments.agentmailbox.to/signed/...
                expires_at: '2026-03-21T04:00:00Z'
        '400':
          description: 'Missing required parameter


            **When this occurs:** The mailbox_id was not provided in the request.
            Either scope the credential to a mailbox or provide mailbox_id in the
            request.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Missing required parameter
                error_id: 550e8400-e29b-41d4-a716-446655440000
                field: mailbox_id
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'Mailbox access denied


            **When this occurs:** Mailbox-scoped credential is attempting to access
            messages from a different mailbox.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Mailbox access denied
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: 'Message not found


            **When this occurs:** The requested message ID does not exist in the database
            or has been deleted.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Message not found
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/messages/{message_id}/analytics:
    get:
      operationId: listSystemMessagesAnalytics
      summary: Get Message Analytics
      tags:
      - messages
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: message_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: UUID of the message
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
          minimum: 0
        description: Number of items to skip for pagination
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 250
        description: Maximum number of items to return
      - name: is_read
        in: query
        schema:
          type: boolean
        description: Filter by read status
      - name: since
        in: query
        schema:
          type: string
          format: date-time
        description: Filter messages after this timestamp (ISO 8601)
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
              example:
                period: 2026-03-01 to 2026-03-04
                summary:
                  sent: 1250
                  delivered: 1235
                  bounced: 15
                  complaints: 2
                  opened: 890
                  clicked: 234
                rates:
                  delivery_rate: 98.8
                  bounce_rate: 1.2
                  open_rate: 72.1
                  click_rate: 18.9
                daily_breakdown:
                - date: '2026-03-04'
                  sent: 320
                  delivered: 318
                  bounced: 2
                  opened: 210
        '400':
          description: 'Missing required parameter


            **When this occurs:** The mailbox_id was not provided in the request.
            Either scope the credential to a mailbox or provide mailbox_id in the
            request.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Missing required parameter
                error_id: 550e8400-e29b-41d4-a716-446655440000
                field: mailbox_id
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'Mailbox access denied


            **When this occurs:** Mailbox-scoped credential is attempting to access
            messages from a different mailbox.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Mailbox access denied
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: 'Message not found


            **When this occurs:** The requested message ID does not exist in the database
            or has been deleted.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Message not found
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/send:
    post:
      operationId: createSystemSend
      summary: Queue email for async sending via S3 outbox pattern with idempotency
      tags:
      - email
      security:
      - hmacSignature: []
      description: Requires 'sending' permission
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - to
              - subject
              properties:
                to:
                  type: array
                  maxItems: 50
                  items:
                    type: string
                    format: email
                  description: Recipient email addresses
                cc:
                  type: array
                  maxItems: 50
                  items:
                    type: string
                    format: email
                bcc:
                  type: array
                  maxItems: 50
                  items:
                    type: string
                    format: email
                subject:
                  type: string
                body_text:
                  type: string
                  description: Plain text body
                body_html:
                  type: string
                  description: HTML body
                reply_to:
                  type: string
                  format: email
                from_mailbox:
                  type: string
                  description: Mailbox username to send from (for credentials with
                    multi-mailbox access)
                attachments:
                  type: array
                  maxItems: 10
                  items:
                    type: object
                    properties:
                      filename:
                        type: string
                      content:
                        type: string
                        format: byte
                      content_type:
                        type: string
                attachment_ids:
                  type: array
                  maxItems: 10
                  items:
                    type: string
                    format: uuid
                  description: Pre-uploaded attachment IDs
                idempotency_key:
                  type: string
                  description: Unique key to prevent duplicate sends
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendEmailResponse'
              example:
                message_id: 8b3f9c5e-f7f7-4fd2-91fa-187f20c3da36
                status: queued
                ses_message_id: 010001234567890a-12345678-1234-1234-1234-123456789012-000000
        '400':
          description: 'Validation error


            **When this occurs:** Attachment failed malware scan. The file has been
            quarantined and cannot be sent.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Malware detected in attachment
                error_id: 550e8400-e29b-41d4-a716-446655440000
                message: File 'document.pdf' contains malware and has been quarantined
                scan_status: quarantined
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'Sending not enabled


            **When this occurs:** Domain does not have sending_enabled=true or domain
            verification is incomplete. Verify DNS records are configured correctly.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Sending not enabled for this domain
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id003
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          description: 'Rate limit exceeded


            **When this occurs:** Tenant has exceeded the hourly send limit (default:
            1000 emails/hour). Wait before sending more emails.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Hourly rate limit exceeded
                error_id: 550e8400-e29b-41d4-a716-446655440000
                message: Maximum 1000 emails per hour for this tenant
                current: 1000
                limit: 1000
                window: 1 hour
                retry_after: 1 hour
  /api/v1/system/tenants/:
    get:
      operationId: listSystemTenants
      summary: Get Authenticated Tenant Info
      tags:
      - tenants
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
          minimum: 0
        description: Number of items to skip for pagination
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 250
        description: Maximum number of items to return
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TenantList'
              example:
                tenants:
                - id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                  codename: acme
                  status: active
                  tier: paid
                  aws_ses_tenant_id: t-abc123def456
                  aws_ses_tenant_name: SES-Tenant-acme
                  configuration_set_name: agentmail-acme-config
                  domain_count: 2
                  mailbox_count: 5
                  created_at: '2026-03-04T10:30:00Z'
                  updated_at: '2026-03-04T10:35:00Z'
                - id: b2c3d4e5-f6a7-8901-bcde-f23456789012
                  codename: beta-corp
                  status: active
                  tier: free
                  aws_ses_tenant_id: t-def456ghi789
                  aws_ses_tenant_name: SES-Tenant-beta-corp
                  configuration_set_name: agentmail-beta-corp-config
                  domain_count: 1
                  mailbox_count: 2
                  created_at: '2026-02-15T08:00:00Z'
                  updated_at: '2026-03-01T14:30:00Z'
                pagination:
                  offset: 0
                  limit: 50
                  total: 2
                  has_more: false
        '400':
          description: Error 400
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id005
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'No accessible tenants


            **When this occurs:** Credential has no tenant associations. User must
            be associated with at least one tenant.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: No accessible tenants
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id003
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/tenants/{tenant_codename}:
    get:
      operationId: getSystemTenants
      summary: Get Tenant Info
      tags:
      - tenants
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: tenant_codename
        in: path
        required: true
        schema:
          type: string
        description: Tenant codename (e.g., 'acme')
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Tenant'
              example: &id006
                id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                codename: acme
                status: active
                tier: paid
                aws_ses_tenant_id: t-abc123def456
                aws_ses_tenant_name: SES-Tenant-acme
                configuration_set_name: agentmail-acme-config
                domains:
                - id: 2ef739e0-dedb-49ef-beb9-86fa70d1b133
                  full_domain: acme.agentmailbox.to
                  verification_status: verified
                  mailbox_count: 3
                statistics:
                  total_domains: 1
                  total_mailboxes: 3
                  total_messages_sent: 1250
                  total_messages_received: 890
                created_at: '2026-03-04T10:30:00Z'
                updated_at: '2026-03-04T10:35:00Z'
        '400':
          description: Error 400
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id005
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'No accessible tenants


            **When this occurs:** Credential has no tenant associations. User must
            be associated with at least one tenant.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: No accessible tenants
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: &id007
                error: Tenant not found
                error_id: 550e8400-e29b-41d4-a716-446655440000
                code: TENANT_NOT_FOUND
                hint: Verify the tenant codename is correct.
                support_url: https://agentmailbox.to/support
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/tenants/{tenant_codename}/analytics:
    get:
      operationId: listSystemTenantsAnalytics
      summary: Get Tenant Analytics
      tags:
      - tenants
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: tenant_codename
        in: path
        required: true
        schema:
          type: string
        description: Tenant codename (e.g., 'acme')
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
          minimum: 0
        description: Number of items to skip for pagination
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 250
        description: Maximum number of items to return
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TenantAnalytics'
              example: &id010
                tenant_codename: acme
                period:
                  start: '2026-03-01T00:00:00Z'
                  end: '2026-03-04T23:59:59Z'
                summary:
                  total_sent: 1250
                  total_delivered: 1242
                  total_bounced: 8
                  total_complaints: 1
                  total_received: 600
                  delivery_rate: 99.4
                  bounce_rate: 0.6
                  complaint_rate: 0.08
                by_domain:
                - domain: acme.agentmailbox.to
                  sent: 1000
                  delivered: 995
                  bounced: 5
                  received: 450
                - domain: support.acme.com
                  sent: 250
                  delivered: 247
                  bounced: 3
                  received: 150
                by_mailbox:
                - mailbox: support@acme.agentmailbox.to
                  sent: 750
                  received: 400
                - mailbox: sales@acme.agentmailbox.to
                  sent: 500
                  received: 200
        '400':
          description: Error 400
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id005
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'No accessible tenants


            **When this occurs:** Credential has no tenant associations. User must
            be associated with at least one tenant.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: No accessible tenants
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id003
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/tenants/{tenant_codename}/domains:
    get:
      operationId: listSystemTenantsDomains
      summary: Get Tenant Domains
      tags:
      - domains
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: tenant_codename
        in: path
        required: true
        schema:
          type: string
        description: Tenant codename (e.g., 'acme')
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
          minimum: 0
        description: Number of items to skip for pagination
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 250
        description: Maximum number of items to return
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DomainList'
              example: *id006
        '400':
          description: Error 400
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id005
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: Error 403
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id002
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id007
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/tenants/{tenant_codename}/mailboxes:
    get:
      operationId: listSystemTenantsMailboxes
      summary: List Tenant Mailboxes
      tags:
      - mailboxes
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: tenant_codename
        in: path
        required: true
        schema:
          type: string
        description: Tenant codename (e.g., 'acme')
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
          minimum: 0
        description: Number of items to skip for pagination
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 250
        description: Maximum number of items to return
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MailboxList'
              example: *id008
        '400':
          description: Error 400
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id005
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'No accessible tenants


            **When this occurs:** The credential has no tenant associations and cannot
            access mailbox data.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: No accessible tenants
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id003
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/tenants/{tenant_codename}/mailboxes/{mailbox_id}/outbound-messages:
    get:
      operationId: listSystemTenantsMailboxesOutboundMessages
      summary: List Mailbox Outbound Messages
      tags:
      - mailboxes
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: tenant_codename
        in: path
        required: true
        schema:
          type: string
        description: Tenant codename (e.g., 'acme')
      - name: mailbox_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: UUID of the mailbox
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
          minimum: 0
        description: Number of items to skip for pagination
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 250
        description: Maximum number of items to return
      - name: is_read
        in: query
        schema:
          type: boolean
        description: Filter by read status
      - name: since
        in: query
        schema:
          type: string
          format: date-time
        description: Filter messages after this timestamp (ISO 8601)
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageList'
              example: *id009
        '400':
          description: 'Missing required parameter


            **When this occurs:** The mailbox_id was not provided in the request.
            Either scope the credential to a mailbox or provide mailbox_id in the
            request.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Missing required parameter
                error_id: 550e8400-e29b-41d4-a716-446655440000
                field: mailbox_id
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'Mailbox access denied


            **When this occurs:** Mailbox-scoped credential is attempting to access
            messages from a different mailbox.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Mailbox access denied
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: 'Message not found


            **When this occurs:** The requested message ID does not exist in the database
            or has been deleted.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Message not found
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/tenants/{tenant_codename}/mailboxes/{mailbox_id}/outbound-messages/{message_id}/analytics:
    get:
      operationId: listSystemTenantsMailboxesOutboundMessagesAnalytics
      summary: Get Mailbox Outbound Message Analytics
      tags:
      - mailboxes
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: tenant_codename
        in: path
        required: true
        schema:
          type: string
        description: Tenant codename (e.g., 'acme')
      - name: mailbox_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: UUID of the mailbox
      - name: message_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: UUID of the message
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
          minimum: 0
        description: Number of items to skip for pagination
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 250
        description: Maximum number of items to return
      - name: is_read
        in: query
        schema:
          type: boolean
        description: Filter by read status
      - name: since
        in: query
        schema:
          type: string
          format: date-time
        description: Filter messages after this timestamp (ISO 8601)
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
              example: *id010
        '400':
          description: 'Missing required parameter


            **When this occurs:** The mailbox_id was not provided in the request.
            Either scope the credential to a mailbox or provide mailbox_id in the
            request.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Missing required parameter
                error_id: 550e8400-e29b-41d4-a716-446655440000
                field: mailbox_id
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'Mailbox access denied


            **When this occurs:** Mailbox-scoped credential is attempting to access
            messages from a different mailbox.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Mailbox access denied
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: 'Message not found


            **When this occurs:** The requested message ID does not exist in the database
            or has been deleted.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Message not found
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/tenants/{tenant_codename}/send-stats:
    get:
      operationId: listSystemTenantsSendStats
      summary: Get Tenant Send Statistics
      tags:
      - tenants
      security:
      - hmacSignature: []
      description: Requires 'receiving' permission
      parameters:
      - name: tenant_codename
        in: path
        required: true
        schema:
          type: string
        description: Tenant codename (e.g., 'acme')
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
          minimum: 0
        description: Number of items to skip for pagination
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 250
        description: Maximum number of items to return
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TenantAnalytics'
              example: *id006
        '400':
          description: Error 400
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id005
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'No accessible tenants


            **When this occurs:** Credential has no tenant associations. User must
            be associated with at least one tenant.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: No accessible tenants
                error_id: 550e8400-e29b-41d4-a716-446655440000
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id007
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /api/v1/system/usage:
    get:
      operationId: listSystemUsage
      summary: Get Usage Status
      tags:
      - usage
      security:
      - hmacSignature: []
      description: Requires 'usage_read' permission
      parameters:
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
          minimum: 0
        description: Number of items to skip for pagination
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 250
        description: Maximum number of items to return
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UsageStatus'
              example:
                tenant_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                tier: free
                billing_enabled: false
                daily_limits:
                  sends: 20
                  receives: 20
                today_usage:
                  sends: 5
                  receives: 12
                held_messages: 0
                upgrade_url: https://agentmailbox.to/upgrade?tenant=acme
        '400':
          description: Error 400
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id005
        '401':
          description: Error 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id001
        '403':
          description: 'Quota exceeded


            **When this occurs:** Free tier daily limit reached. Upgrade to paid tier
            for higher limits or wait until tomorrow.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Daily quota exceeded
                error_id: 550e8400-e29b-41d4-a716-446655440000
                current: 20
                limit: 20
                tier: free
        '404':
          description: Error 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id003
        '500':
          description: Error 500
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example: *id004
        '429':
          $ref: '#/components/responses/TooManyRequests'
components:
  securitySchemes:
    cognitoJwt:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: '**JWT (Customer Authenticated)** - Cognito JWT token for the customer
        portal web UI and user sessions. Obtain via Cognito authentication flow at
        the customer login page.'
    hmacSignature:
      type: apiKey
      in: header
      name: X-Signature
      description: '**HMAC (AI Agent / Programmatic)** - HMAC-SHA256 signature for
        programmatic API access and AI agents.


        Required headers:

        - `X-API-Key`: Your API key ID (e.g., `MK-xxx` for mailbox, `AK-xxx` for tenant
        admin)

        - `X-Timestamp`: Unix timestamp in seconds

        - `X-Body-Hash`: SHA256 hash of request body (base64-encoded)

        - `X-Signature`: HMAC-SHA256 signature (hex-encoded)


        Signature format:

        ```

        string_to_sign = f"{METHOD}\n{PATH}\n{CANONICAL_QUERY}\n{BODY_HASH}\n{TIMESTAMP}"

        signature = hmac.new(api_secret.encode(), string_to_sign.encode(), hashlib.sha256).hexdigest()

        ```


        See the Authentication section above for complete Python code example.'
  schemas:
    Error:
      type: object
      required:
      - error
      - error_id
      properties:
        error:
          type: string
          description: Error description (what failed)
        error_id:
          type: string
          format: uuid
          description: Unique error ID for support correlation
        code:
          type: string
          description: Machine-readable error code (e.g., DOMAIN_NOT_FOUND)
        message:
          type: string
          description: User-friendly error message
        hint:
          type: string
          description: Suggestion for resolving the error
        support_url:
          type: string
          format: uri
          description: URL for additional support
        field:
          type: string
          description: Field that caused validation error (400 errors only)
        missing_records:
          type: array
          items:
            type: string
          description: Missing DNS records (DNS verification errors only)
        suggestions:
          type: array
          items:
            type: string
          description: Alternative suggestions (409 Conflict only)
        allowed_methods:
          type: array
          items:
            type: string
          description: List of allowed HTTP methods (405 Method Not Allowed only)
    SuccessResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        message:
          type: string
    ResourceDiscoveryResponse:
      type: object
      description: Response from tenant resource discovery
      properties:
        tenants:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
              codename:
                type: string
              status:
                type: string
              domains:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: string
                      format: uuid
                    full_domain:
                      type: string
                    status:
                      type: string
                    mailboxes:
                      type: array
                      items:
                        type: object
                        properties:
                          id:
                            type: string
                            format: uuid
                          email:
                            type: string
                          status:
                            type: string
        summary:
          type: object
          properties:
            total_tenants:
              type: integer
            total_domains:
              type: integer
            total_mailboxes:
              type: integer
        discovered_at:
          type: string
          format: date-time
    DnsVerifyBatchResponse:
      type: object
      description: Response from batch DNS verification
      properties:
        batch_id:
          type: string
        total_domains:
          type: integer
        results:
          type: array
          items:
            type: object
            properties:
              domain_id:
                type: string
                format: uuid
              domain:
                type: string
              status:
                type: string
              dkim_status:
                type: string
              errors:
                type: array
                items:
                  type: string
        summary:
          type: object
          properties:
            verified:
              type: integer
            pending:
              type: integer
            failed:
              type: integer
    DeleteResponse:
      type: object
      properties:
        deleted:
          type: boolean
        id:
          type: string
          format: uuid
    Pagination:
      type: object
      properties:
        offset:
          type: integer
        limit:
          type: integer
        total:
          type: integer
        has_more:
          type: boolean
    Tenant:
      type: object
      properties:
        id:
          type: string
          format: uuid
        codename:
          type: string
          description: Unique identifier (e.g., 'acme')
        status:
          type: string
          enum:
          - active
          - suspended
          - pending
        tier:
          type: string
          enum:
          - free
          - paid
        aws_ses_tenant_id:
          type: string
        aws_ses_tenant_name:
          type: string
        configuration_set_name:
          type: string
        domain_count:
          type: integer
        mailbox_count:
          type: integer
        domains:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
              full_domain:
                type: string
              verification_status:
                type: string
              mailbox_count:
                type: integer
        statistics:
          type: object
          properties:
            total_domains:
              type: integer
            total_mailboxes:
              type: integer
            total_messages_sent:
              type: integer
            total_messages_received:
              type: integer
        previous_status:
          type: string
          description: Status before reactivation
        reactivated_at:
          type: string
          format: date-time
        reactivated_by:
          type: string
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    TenantList:
      type: object
      properties:
        tenants:
          type: array
          items:
            $ref: '#/components/schemas/Tenant'
        pagination:
          $ref: '#/components/schemas/Pagination'
    Domain:
      type: object
      properties:
        id:
          type: string
          format: uuid
        tenant_id:
          type: string
          format: uuid
        tenant_codename:
          type: string
        full_domain:
          type: string
          description: e.g., 'acme.agentmailbox.to'
        subdomain:
          type: string
        parent_domain:
          type: string
        verification_status:
          type: string
          enum:
          - pending
          - verified
          - failed
        dkim_status:
          type: string
          enum:
          - pending
          - verified
          - failed
        sending_enabled:
          type: boolean
        receiving_enabled:
          type: boolean
        ses_identity_arn:
          type: string
        mailbox_count:
          type: integer
        mailboxes:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
              email:
                type: string
                format: email
              display_name:
                type: string
              status:
                type: string
        dns_records:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
              name:
                type: string
              value:
                type: string
              status:
                type: string
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    DomainList:
      type: object
      properties:
        domains:
          type: array
          items:
            $ref: '#/components/schemas/Domain'
        pagination:
          $ref: '#/components/schemas/Pagination'
    DnsStatus:
      type: object
      properties:
        domain:
          type: string
        verification_status:
          type: string
        dkim_status:
          type: string
        spf_status:
          type: string
        dmarc_status:
          type: string
        sending_enabled:
          type: boolean
        receiving_enabled:
          type: boolean
        required_records:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
              name:
                type: string
              value:
                type: string
              status:
                type: string
              verified_at:
                type: string
                format: date-time
        ai_explanation:
          type: string
          description: AI-generated setup guide
    Subdomain:
      type: object
      properties:
        id:
          type: string
          format: uuid
        subdomain:
          type: string
        full_domain:
          type: string
        tenant_id:
          type: string
          format: uuid
        tenant_codename:
          type: string
        status:
          type: string
          enum:
          - active
          - suspended
          - pending
        verification_status:
          type: string
        mailbox_count:
          type: integer
        created_at:
          type: string
          format: date-time
    SubdomainList:
      type: object
      properties:
        subdomains:
          type: array
          items:
            $ref: '#/components/schemas/Subdomain'
        pagination:
          $ref: '#/components/schemas/Pagination'
    SubdomainCreated:
      type: object
      properties:
        id:
          type: string
          format: uuid
        subdomain:
          type: string
        full_domain:
          type: string
        tenant_id:
          type: string
          format: uuid
        tenant_codename:
          type: string
        status:
          type: string
        mailboxes:
          type: array
          items:
            $ref: '#/components/schemas/Mailbox'
        dns_records:
          type: array
          items:
            type: object
        credential_retrieval_url:
          type: string
          format: uri
          description: One-time URL to retrieve API credentials
    Mailbox:
      type: object
      properties:
        id:
          type: string
          format: uuid
        domain_id:
          type: string
          format: uuid
        username:
          type: string
          description: Local part of email
        display_name:
          type: string
        email_address:
          type: string
          format: email
        created_at:
          type: string
          format: date-time
    MailboxList:
      type: object
      properties:
        mailboxes:
          type: array
          items:
            $ref: '#/components/schemas/Mailbox'
        pagination:
          $ref: '#/components/schemas/Pagination'
    CredentialCreated:
      type: object
      description: Only returned once at creation time
      properties:
        api_key_id:
          type: string
          description: Public API key (MK-xxx or AK-xxx)
        api_secret:
          type: string
          description: Secret key (shown only once)
        permissions:
          type: string
          enum:
          - sending_only
          - receiving_only
          - admin
        mailbox_id:
          type: string
          format: uuid
          nullable: true
        created_at:
          type: string
          format: date-time
    CredentialList:
      type: object
      properties:
        credentials:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
              api_key_id:
                type: string
              permissions:
                type: string
              mailbox_id:
                type: string
                format: uuid
                nullable: true
              created_at:
                type: string
                format: date-time
              last_used_at:
                type: string
                format: date-time
                nullable: true
    Message:
      type: object
      properties:
        id:
          type: string
          format: uuid
        mailbox_id:
          type: string
          format: uuid
        message_id:
          type: string
          description: Email Message-ID header
        thread_id:
          type: string
          format: uuid
        direction:
          type: string
          enum:
          - inbound
          - outbound
        from_address:
          type: string
          format: email
        to_addresses:
          type: array
          items:
            type: string
            format: email
        subject:
          type: string
        body_text:
          type: string
        body_html:
          type: string
        timestamp:
          type: string
          format: date-time
        is_read:
          type: boolean
        is_archived:
          type: boolean
        has_attachments:
          type: boolean
        attachments:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
              filename:
                type: string
              content_type:
                type: string
              size_bytes:
                type: integer
              download_url:
                type: string
                format: uri
    MessageList:
      type: object
      properties:
        messages:
          type: array
          items:
            $ref: '#/components/schemas/Message'
        total:
          type: integer
        limit:
          type: integer
        offset:
          type: integer
    AttachmentDownload:
      type: object
      description: Attachment metadata with presigned download URL
      properties:
        id:
          type: string
          format: uuid
        filename:
          type: string
        content_type:
          type: string
        size_bytes:
          type: integer
        download_url:
          type: string
          format: uri
          description: Presigned URL for downloading the attachment (expires after
            1 hour)
        expires_at:
          type: string
          format: date-time
          description: When the download URL expires
      required:
      - id
      - filename
      - content_type
      - size_bytes
      - download_url
    SendEmailResponse:
      type: object
      properties:
        message_id:
          type: string
          format: uuid
        status:
          type: string
          enum:
          - queued
          - sending
          - sent
          - held
        ses_message_id:
          type: string
          nullable: true
        held_reason:
          type: string
          nullable: true
          description: Reason if message was held (e.g., quota exceeded)
    Analytics:
      type: object
      description: Basic analytics data
      properties:
        period:
          type: string
        sent:
          type: integer
        delivered:
          type: integer
        bounced:
          type: integer
        complaints:
          type: integer
        opened:
          type: integer
        clicked:
          type: integer
        delivery_rate:
          type: number
        open_rate:
          type: number
        click_rate:
          type: number
    PortalAnalytics:
      type: object
      description: Analytics data for portal endpoints
      properties:
        period:
          type: string
        summary:
          type: object
          properties:
            sent:
              type: integer
            delivered:
              type: integer
            bounced:
              type: integer
            complaints:
              type: integer
            opened:
              type: integer
            clicked:
              type: integer
        rates:
          type: object
          properties:
            delivery_rate:
              type: number
            bounce_rate:
              type: number
            open_rate:
              type: number
            click_rate:
              type: number
        daily_breakdown:
          type: array
          items:
            type: object
            properties:
              date:
                type: string
                format: date
              sent:
                type: integer
              delivered:
                type: integer
              bounced:
                type: integer
              opened:
                type: integer
    RealtimeMetrics:
      type: object
      description: Realtime metrics for a domain
      properties:
        domain:
          type: string
        period:
          type: string
        metrics:
          type: object
          properties:
            emails_sent:
              type: integer
            emails_delivered:
              type: integer
            emails_bounced:
              type: integer
            emails_complained:
              type: integer
            emails_received:
              type: integer
            delivery_rate:
              type: number
            bounce_rate:
              type: number
            complaint_rate:
              type: number
        last_updated:
          type: string
          format: date-time
    DailyMetrics:
      type: object
      description: Daily metrics breakdown
      properties:
        domain:
          type: string
        period:
          type: object
          properties:
            start:
              type: string
              format: date
            end:
              type: string
              format: date
        daily_stats:
          type: array
          items:
            type: object
            properties:
              date:
                type: string
                format: date
              sent:
                type: integer
              delivered:
                type: integer
              bounced:
                type: integer
              complaints:
                type: integer
              received:
                type: integer
        totals:
          type: object
          properties:
            sent:
              type: integer
            delivered:
              type: integer
            bounced:
              type: integer
            complaints:
              type: integer
            received:
              type: integer
    MonthlyMetrics:
      type: object
      description: Monthly metrics summary
      properties:
        domain:
          type: string
        period:
          type: object
          properties:
            year:
              type: integer
            month:
              type: integer
        summary:
          type: object
          properties:
            total_sent:
              type: integer
            total_delivered:
              type: integer
            total_bounced:
              type: integer
            total_complaints:
              type: integer
            total_received:
              type: integer
            delivery_rate:
              type: number
            bounce_rate:
              type: number
            complaint_rate:
              type: number
        top_senders:
          type: array
          items:
            type: object
            properties:
              mailbox:
                type: string
              count:
                type: integer
    TrackingConfig:
      type: object
      description: Email tracking configuration for a domain
      properties:
        domain:
          type: string
        open_tracking:
          type: boolean
        click_tracking:
          type: boolean
        custom_tracking_domain:
          type: string
          nullable: true
        webhook_url:
          type: string
          format: uri
        webhook_events:
          type: array
          items:
            type: string
            enum:
            - delivered
            - bounced
            - complained
            - opened
            - clicked
        updated_at:
          type: string
          format: date-time
        message:
          type: string
    TenantAnalytics:
      type: object
      description: Tenant-wide analytics summary
      properties:
        tenant_codename:
          type: string
        period:
          type: object
          properties:
            start:
              type: string
              format: date-time
            end:
              type: string
              format: date-time
        summary:
          type: object
          properties:
            total_sent:
              type: integer
            total_delivered:
              type: integer
            total_bounced:
              type: integer
            total_complaints:
              type: integer
            total_received:
              type: integer
            delivery_rate:
              type: number
            bounce_rate:
              type: number
            complaint_rate:
              type: number
        by_domain:
          type: array
          items:
            type: object
            properties:
              domain:
                type: string
              sent:
                type: integer
              delivered:
                type: integer
              bounced:
                type: integer
              received:
                type: integer
        by_mailbox:
          type: array
          items:
            type: object
            properties:
              mailbox:
                type: string
              sent:
                type: integer
              received:
                type: integer
    DomainAnalytics:
      type: object
      description: Domain-specific analytics
      properties:
        domain:
          type: string
        period:
          type: string
        sent:
          type: integer
        delivered:
          type: integer
        bounced:
          type: integer
        complaints:
          type: integer
        received:
          type: integer
        delivery_rate:
          type: number
        bounce_rate:
          type: number
        complaint_rate:
          type: number
    DomainVerificationResult:
      type: object
      description: Result of domain verification operation
      properties:
        domain:
          type: string
        verification_triggered:
          type: boolean
        previous_status:
          type: string
          enum:
          - pending
          - verified
          - failed
        current_status:
          type: string
          enum:
          - pending
          - verified
          - failed
        verification_duration_ms:
          type: integer
        dkim_verified:
          type: boolean
        message:
          type: string
    OutboundMessageList:
      type: object
      description: List of outbound messages with pagination
      properties:
        messages:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
              mailbox_id:
                type: string
                format: uuid
              from_address:
                type: string
                format: email
              to_addresses:
                type: array
                items:
                  type: string
                  format: email
              subject:
                type: string
              status:
                type: string
                enum:
                - queued
                - sent
                - delivered
                - bounced
              ses_message_id:
                type: string
              sent_at:
                type: string
                format: date-time
              delivered_at:
                type: string
                format: date-time
                nullable: true
              bounced_at:
                type: string
                format: date-time
                nullable: true
              bounce_type:
                type: string
                nullable: true
              bounce_subtype:
                type: string
                nullable: true
        pagination:
          type: object
          properties:
            offset:
              type: integer
            limit:
              type: integer
            total:
              type: integer
            has_more:
              type: boolean
    MessageAnalytics:
      type: object
      description: Analytics for a specific message
      properties:
        message_id:
          type: string
          format: uuid
        from_address:
          type: string
          format: email
        to_addresses:
          type: array
          items:
            type: string
            format: email
        subject:
          type: string
        status:
          type: string
        timeline:
          type: array
          items:
            type: object
            properties:
              event:
                type: string
              timestamp:
                type: string
                format: date-time
              user_agent:
                type: string
              url:
                type: string
        open_count:
          type: integer
        click_count:
          type: integer
        unique_opens:
          type: integer
        unique_clicks:
          type: integer
    UsageStatus:
      type: object
      properties:
        tenant_id:
          type: string
          format: uuid
        tier:
          type: string
          enum:
          - free
          - paid
        current_period:
          type: object
          properties:
            start:
              type: string
              format: date-time
            end:
              type: string
              format: date-time
            emails_sent:
              type: integer
            emails_received:
              type: integer
        limits:
          type: object
          properties:
            monthly_outbound:
              type: integer
            daily_outbound:
              type: integer
        held_messages:
          type: integer
          description: Messages held due to quota
  responses:
    BadRequest:
      description: 'Bad request - validation error


        **Common causes:**

        - Invalid email format in to/cc/bcc fields

        - Missing required fields (subject, recipients)

        - Invalid attachment format or base64 encoding

        - Attachment failed malware scan

        - Malware scan still pending (retry after a few seconds)


        **Resolution:** Check the `field` property in the response to identify which
        field caused the validation error.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Invalid email format
            error_id: 550e8400-e29b-41d4-a716-446655440000
            field: to
    Unauthorized:
      description: 'Authentication required


        **Common causes:**

        - Missing or malformed Authorization header

        - Invalid or expired JWT token

        - Invalid or expired HMAC signature (if using HMAC auth)

        - Signature timestamp drift > 5 minutes (HMAC auth)


        **Resolution:** Verify your authentication credentials and retry. For JWT,
        obtain a fresh token. For HMAC, regenerate signature with current timestamp.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Authentication required
            error_id: 550e8400-e29b-41d4-a716-446655440001
            message: Invalid or expired authentication
    Forbidden:
      description: 'Insufficient permissions


        **Common causes:**

        - Credential has wrong permission type (e.g., receiving_only trying to send)

        - Mailbox-scoped credential accessing different mailbox

        - Cross-tenant access without proper authorization

        - Domain sending not enabled or verification incomplete

        - Unauthorized tenant access for admin operations


        **Resolution:** Check credential permissions match the operation. Verify domain
        is fully verified for sending.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Unauthorized send permission
            error_id: 550e8400-e29b-41d4-a716-446655440002
            message: This credential does not have permission to send emails
    NotFound:
      description: 'Resource not found


        **Common causes:**

        - Message ID does not exist

        - Mailbox does not exist or was deleted

        - Attachment reference not found in S3

        - Resource belongs to different tenant


        **Resolution:** Verify the resource ID is correct. Check you have access to
        the resource''s tenant.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Message not found
            error_id: 550e8400-e29b-41d4-a716-446655440003
    TooManyRequests:
      description: 'Rate limit exceeded


        **Rate limits (per tenant):**

        - Hourly: 1,000 emails/hour (default)

        - Daily: 1,000 emails/day (default, upgradeable)

        - Per recipient group: 100 emails/hour


        **Resolution:** Wait for the rate limit window to reset. Consider upgrading
        to paid tier for higher limits.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Hourly rate limit exceeded
            error_id: 550e8400-e29b-41d4-a716-446655440004
            message: Maximum 1000 emails per hour for this tenant
            current: 1000
            limit: 1000
            window: 1 hour
            retry_after: 1 hour
    Conflict:
      description: 'Resource conflict (duplicate, already exists)


        **Common causes:**

        - Subdomain is already taken by another tenant

        - Mailbox with same email address already exists

        - Duplicate credential name


        **Resolution:** Choose a different name. Check `suggestions` field for alternatives.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Subdomain 'acme' is already taken
            error_id: 550e8400-e29b-41d4-a716-446655440006
            suggestions:
            - acme1
            - acme2
            - acme-corp
    MethodNotAllowed:
      description: HTTP method not allowed for this endpoint
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Method not allowed
            error_id: 550e8400-e29b-41d4-a716-446655440007
            allowed_methods:
            - GET
            - POST
    InternalError:
      description: 'Internal server error


        **Common causes:**

        - Database connectivity issues

        - S3 presigned URL generation failed

        - Configuration set validation failed

        - Unexpected exception during processing


        **Resolution:** Retry the request. If error persists, contact support with
        the `error_id` for investigation.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Failed to process request
            error_id: 550e8400-e29b-41d4-a716-446655440005
            message: An error occurred while processing your request. Please contact
              support with the error ID if this persists.
  parameters:
    offsetParam:
      name: offset
      in: query
      schema:
        type: integer
        default: 0
        minimum: 0
      description: Number of items to skip
    limitParam:
      name: limit
      in: query
      schema:
        type: integer
        default: 50
        minimum: 1
        maximum: 250
      description: Maximum items to return
