openapi: 3.0.3
info:
  title: Email API Worker
  description: |
    Comprehensive email management API with Microsoft Graph integration, deployed on Cloudflare Workers.

    Features:
    - Send and receive emails via Microsoft 365
    - Email alias support
    - Attachment handling
    - Link click tracking
    - Webhook notifications
    - Complete audit logging
    - Error tracking and monitoring
  version: 1.0.0
  contact:
    name: API Support
    email: support@example.com
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT

servers:
  - url: https://your-worker.workers.dev
    description: Production server
  - url: http://localhost:8787
    description: Local development server

tags:
  - name: Messages
    description: Email message operations
  - name: Send
    description: Send and reply to emails
  - name: Attachments
    description: Handle email attachments
  - name: Tracking
    description: Link click tracking and analytics
  - name: Webhooks
    description: Inbound email webhooks
  - name: Logs
    description: Activity and error logs
  - name: Health
    description: Service health checks

paths:
  /health:
    get:
      tags:
        - Health
      summary: Health check
      description: Check if the API is operational
      operationId: healthCheck
      responses:
        '200':
          description: Service is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  timestamp:
                    type: string
                    format: date-time

  /api/messages:
    get:
      tags:
        - Messages
      summary: List messages
      description: Fetch emails for a specific user with optional filtering
      operationId: listMessages
      parameters:
        - name: email
          in: query
          required: true
          description: User email address
          schema:
            type: string
            format: email
            example: user@domain.com
        - name: limit
          in: query
          required: false
          description: Maximum number of messages to return
          schema:
            type: integer
            default: 50
            minimum: 1
            maximum: 100
        - name: unread
          in: query
          required: false
          description: Filter for unread messages only
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: Successfully retrieved messages
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  count:
                    type: integer
                    example: 10
                  emails:
                    type: array
                    items:
                      $ref: '#/components/schemas/EmailMessage'
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalError'

  /api/messages/{messageId}:
    get:
      tags:
        - Messages
      summary: Get single message
      description: Retrieve a specific message with full body content
      operationId: getMessage
      parameters:
        - name: messageId
          in: path
          required: true
          description: Message ID
          schema:
            type: string
        - name: email
          in: query
          required: true
          description: User email address
          schema:
            type: string
            format: email
      responses:
        '200':
          description: Successfully retrieved message
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  email:
                    $ref: '#/components/schemas/EmailMessageDetailed'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'

  /api/messages/{messageId}/attachments:
    get:
      tags:
        - Attachments
      summary: List message attachments
      description: Get all attachments for a specific message
      operationId: listAttachments
      parameters:
        - name: messageId
          in: path
          required: true
          description: Message ID
          schema:
            type: string
        - name: email
          in: query
          required: true
          description: User email address
          schema:
            type: string
            format: email
      responses:
        '200':
          description: Successfully retrieved attachments
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  count:
                    type: integer
                  attachments:
                    type: array
                    items:
                      $ref: '#/components/schemas/Attachment'
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalError'

  /api/attachments/{attachmentId}:
    get:
      tags:
        - Attachments
      summary: Download attachment
      description: Download a specific attachment
      operationId: downloadAttachment
      parameters:
        - name: attachmentId
          in: path
          required: true
          description: Attachment ID
          schema:
            type: string
        - name: email
          in: query
          required: true
          description: User email address
          schema:
            type: string
            format: email
        - name: messageId
          in: query
          required: true
          description: Message ID
          schema:
            type: string
      responses:
        '200':
          description: Successfully retrieved attachment
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  attachment:
                    $ref: '#/components/schemas/AttachmentContent'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'

  /api/send:
    post:
      tags:
        - Send
      summary: Send email
      description: Send a new email with optional attachments and link tracking
      operationId: sendEmail
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendEmailRequest'
      responses:
        '200':
          description: Email sent successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: Email sent successfully
                  sentEmailId:
                    type: integer
                    example: 123
                  trackedLinksCount:
                    type: integer
                    example: 3
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalError'

  /api/reply/{messageId}:
    post:
      tags:
        - Send
      summary: Reply to message
      description: Send a reply to an existing message
      operationId: replyToMessage
      parameters:
        - name: messageId
          in: path
          required: true
          description: Message ID to reply to
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReplyRequest'
      responses:
        '200':
          description: Reply sent successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: Reply sent successfully
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalError'

  /api/logs:
    get:
      tags:
        - Logs
      summary: Get email activity logs
      description: Retrieve email operation logs with optional filtering
      operationId: getEmailLogs
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 100
            maximum: 500
        - name: action
          in: query
          required: false
          description: Filter by action type
          schema:
            type: string
            enum: [fetch, send, reply, link_click]
      responses:
        '200':
          description: Successfully retrieved logs
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  count:
                    type: integer
                  logs:
                    type: array
                    items:
                      $ref: '#/components/schemas/EmailLog'
        '500':
          $ref: '#/components/responses/InternalError'

  /api/webhook-logs:
    get:
      tags:
        - Logs
      summary: Get webhook logs
      description: Retrieve webhook notification logs
      operationId: getWebhookLogs
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 100
      responses:
        '200':
          description: Successfully retrieved webhook logs
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  count:
                    type: integer
                  logs:
                    type: array
                    items:
                      $ref: '#/components/schemas/WebhookLog'
        '500':
          $ref: '#/components/responses/InternalError'

  /api/sent-emails:
    get:
      tags:
        - Logs
      summary: Get sent email history
      description: Retrieve history of sent emails
      operationId: getSentEmails
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 100
        - name: status
          in: query
          required: false
          description: Filter by email status
          schema:
            type: string
            enum: [success, failed, pending]
        - name: from
          in: query
          required: false
          description: Filter by sender email
          schema:
            type: string
            format: email
      responses:
        '200':
          description: Successfully retrieved sent emails
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  count:
                    type: integer
                  emails:
                    type: array
                    items:
                      $ref: '#/components/schemas/SentEmail'
        '500':
          $ref: '#/components/responses/InternalError'

  /api/errors:
    get:
      tags:
        - Logs
      summary: Get error logs
      description: Retrieve error logs with optional filtering
      operationId: getErrors
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 100
        - name: type
          in: query
          required: false
          description: Filter by error type
          schema:
            type: string
            enum: [fetch, send, webhook, attachment, auth, tracking]
        - name: unresolved
          in: query
          required: false
          description: Show only unresolved errors
          schema:
            type: boolean
      responses:
        '200':
          description: Successfully retrieved errors
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  count:
                    type: integer
                  errors:
                    type: array
                    items:
                      $ref: '#/components/schemas/EmailError'
        '500':
          $ref: '#/components/responses/InternalError'

  /api/errors/{errorId}/resolve:
    patch:
      tags:
        - Logs
      summary: Mark error as resolved
      description: Mark a specific error as resolved
      operationId: resolveError
      parameters:
        - name: errorId
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Error marked as resolved
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: Error marked as resolved
        '500':
          $ref: '#/components/responses/InternalError'

  /webhook/inbound:
    post:
      tags:
        - Webhooks
      summary: Inbound email webhook
      description: Webhook endpoint for Microsoft Graph notifications
      operationId: inboundWebhook
      parameters:
        - name: X-Webhook-Secret
          in: header
          required: true
          description: Webhook authentication secret
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookPayload'
      responses:
        '200':
          description: Webhook processed successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  processed:
                    type: integer
                    example: 1
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalError'

  /track/click/{trackingId}:
    get:
      tags:
        - Tracking
      summary: Track link click
      description: Track link click and redirect to original URL
      operationId: trackClick
      parameters:
        - name: trackingId
          in: path
          required: true
          description: Unique tracking ID
          schema:
            type: string
            format: uuid
      responses:
        '302':
          description: Redirecting to original URL
          headers:
            Location:
              schema:
                type: string
                format: uri
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'

  /api/tracking/{sentEmailId}:
    get:
      tags:
        - Tracking
      summary: Get email click analytics
      description: Get detailed click analytics for a specific sent email
      operationId: getEmailAnalytics
      parameters:
        - name: sentEmailId
          in: path
          required: true
          description: Sent email ID
          schema:
            type: integer
      responses:
        '200':
          description: Successfully retrieved analytics
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  sentEmailId:
                    type: integer
                  analytics:
                    $ref: '#/components/schemas/ClickAnalytics'
        '500':
          $ref: '#/components/responses/InternalError'

  /api/tracking/stats:
    get:
      tags:
        - Tracking
      summary: Get tracking statistics
      description: Get overall tracking statistics across multiple emails
      operationId: getTrackingStats
      parameters:
        - name: from
          in: query
          required: false
          description: Filter by sender email
          schema:
            type: string
            format: email
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 10
      responses:
        '200':
          description: Successfully retrieved statistics
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  count:
                    type: integer
                  stats:
                    type: array
                    items:
                      $ref: '#/components/schemas/EmailStats'
        '500':
          $ref: '#/components/responses/InternalError'

components:
  schemas:
    EmailMessage:
      type: object
      properties:
        id:
          type: string
        subject:
          type: string
        from:
          type: string
          format: email
        fromName:
          type: string
        toRecipients:
          type: array
          items:
            type: string
            format: email
        ccRecipients:
          type: array
          items:
            type: string
            format: email
        receivedDateTime:
          type: string
          format: date-time
        bodyPreview:
          type: string
        isRead:
          type: boolean
        hasAttachments:
          type: boolean
        importance:
          type: string
          enum: [low, normal, high]
        receivedAtAlias:
          type: string
          format: email

    EmailMessageDetailed:
      allOf:
        - $ref: '#/components/schemas/EmailMessage'
        - type: object
          properties:
            body:
              type: object
              properties:
                content:
                  type: string
                contentType:
                  type: string
                  enum: [Text, HTML]

    Attachment:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        contentType:
          type: string
        size:
          type: integer
        isInline:
          type: boolean

    AttachmentContent:
      allOf:
        - $ref: '#/components/schemas/Attachment'
        - type: object
          properties:
            contentBytes:
              type: string
              format: byte
              description: Base64 encoded content

    SendEmailRequest:
      type: object
      required:
        - from
        - to
        - subject
        - body
      properties:
        from:
          type: string
          format: email
          description: Sender email address
        fromAlias:
          type: string
          format: email
          description: Send from this alias
        to:
          oneOf:
            - type: string
              format: email
            - type: array
              items:
                type: string
                format: email
          description: Recipient email address(es)
        cc:
          oneOf:
            - type: string
              format: email
            - type: array
              items:
                type: string
                format: email
          description: CC recipients
        bcc:
          oneOf:
            - type: string
              format: email
            - type: array
              items:
                type: string
                format: email
          description: BCC recipients
        subject:
          type: string
          description: Email subject
        body:
          type: string
          description: Email body content
        contentType:
          type: string
          enum: [Text, HTML]
          default: HTML
        replyTo:
          type: string
          format: email
          description: Reply-to address
        enableTracking:
          type: boolean
          default: false
          description: Enable link click tracking
        attachments:
          type: array
          items:
            type: object
            required:
              - name
              - contentBytes
            properties:
              name:
                type: string
              contentType:
                type: string
                default: application/octet-stream
              contentBytes:
                type: string
                format: byte
                description: Base64 encoded content

    ReplyRequest:
      type: object
      required:
        - userEmail
        - replyText
      properties:
        userEmail:
          type: string
          format: email
        replyText:
          type: string
        contentType:
          type: string
          enum: [Text, HTML]
          default: Text
        attachments:
          type: array
          items:
            type: object
            required:
              - name
              - contentBytes
            properties:
              name:
                type: string
              contentType:
                type: string
              contentBytes:
                type: string
                format: byte

    EmailLog:
      type: object
      properties:
        id:
          type: integer
        action:
          type: string
          enum: [fetch, send, reply, link_click]
        userEmail:
          type: string
          format: email
        recipient:
          type: string
          format: email
        subject:
          type: string
        metadata:
          type: string
          description: JSON string with additional details
        timestamp:
          type: string
          format: date-time

    WebhookLog:
      type: object
      properties:
        id:
          type: integer
        resource:
          type: string
        changeType:
          type: string
        payload:
          type: string
          description: JSON string with webhook payload
        timestamp:
          type: string
          format: date-time

    SentEmail:
      type: object
      properties:
        id:
          type: integer
        messageId:
          type: string
        fromEmail:
          type: string
          format: email
        fromAlias:
          type: string
          format: email
        toRecipients:
          type: string
          description: JSON array of recipients
        ccRecipients:
          type: string
        bccRecipients:
          type: string
        subject:
          type: string
        bodyPreview:
          type: string
        contentType:
          type: string
        hasAttachments:
          type: boolean
        attachmentCount:
          type: integer
        status:
          type: string
          enum: [success, failed, pending]
        errorMessage:
          type: string
        sentAt:
          type: string
          format: date-time
        metadata:
          type: string

    EmailError:
      type: object
      properties:
        id:
          type: integer
        errorType:
          type: string
          enum: [fetch, send, webhook, attachment, auth, tracking]
        errorCode:
          type: string
        errorMessage:
          type: string
        userEmail:
          type: string
          format: email
        messageId:
          type: string
        endpoint:
          type: string
        requestPayload:
          type: string
        responsePayload:
          type: string
        stackTrace:
          type: string
        timestamp:
          type: string
          format: date-time
        resolved:
          type: boolean

    WebhookPayload:
      type: object
      properties:
        value:
          type: array
          items:
            type: object
            properties:
              subscriptionId:
                type: string
              changeType:
                type: string
              resource:
                type: string
              resourceData:
                type: object
              clientState:
                type: string

    ClickAnalytics:
      type: object
      properties:
        totalLinks:
          type: integer
          description: Total number of links in the email
        clickedLinks:
          type: integer
          description: Number of unique links clicked
        totalClicks:
          type: integer
          description: Total number of clicks across all links
        clickRate:
          type: string
          description: Percentage of links clicked
          example: "60.00"
        links:
          type: array
          items:
            type: object
            properties:
              originalUrl:
                type: string
                format: uri
              trackingId:
                type: string
                format: uuid
              clickCount:
                type: integer
              lastClickedAt:
                type: string
                format: date-time
              ipAddress:
                type: string
              userAgent:
                type: string
              referer:
                type: string

    EmailStats:
      type: object
      properties:
        sentEmailId:
          type: integer
        subject:
          type: string
        fromEmail:
          type: string
          format: email
        toRecipients:
          type: array
          items:
            type: string
            format: email
        sentAt:
          type: string
          format: date-time
        totalLinks:
          type: integer
        clickedLinks:
          type: integer
        totalClicks:
          type: integer
        clickRate:
          type: string
          example: "60.00"

    Error:
      type: object
      properties:
        error:
          type: string
        details:
          type: object

  responses:
    BadRequest:
      description: Bad request - invalid parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: email parameter required

    Unauthorized:
      description: Unauthorized - invalid credentials
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Unauthorized

    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Resource not found

    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Internal server error

  securitySchemes:
    WebhookSecret:
      type: apiKey
      in: header
      name: X-Webhook-Secret
      description: Secret key for webhook authentication

security:
  - WebhookSecret: []
