openapi: 3.0.3
info:
  title: Mailcoach API
  description: |
    REST API for Laravel Mailcoach — send email campaigns, manage subscribers,
    and handle transactional mails.

    Authentication is via Bearer token (Laravel Sanctum).
    All collection endpoints return paginated responses using the standard
    Laravel pagination envelope (`data`, `links`, `meta`).

    Filtering uses the `?filter[key]=value` convention
    (spatie/laravel-query-builder). Sorting uses `?sort=field` (ascending)
    or `?sort=-field` (descending).
  version: 1.0.0
  contact:
    name: Spatie
    url: https://mailcoach.app
servers:
  - url: '{baseUrl}/api'
    description: Mailcoach API
    variables:
      baseUrl:
        default: https://your-app.com
        description: The base URL of your Mailcoach installation
security:
  - bearerAuth: []
tags:
  - name: Templates
    description: Reusable email templates
  - name: Suppressions
    description: Globally suppressed email addresses
  - name: Lists
    description: Audience lists
  - name: Tags
    description: Tags within a list
  - name: Segments
    description: Tag-based segments within a list
  - name: Subscribers
    description: Subscribers of a list
  - name: Campaigns
    description: Email campaigns
  - name: Campaign Statistics
    description: Opens, clicks, unsubscribes, and bounces for a campaign
  - name: Sends
    description: Individual sends (one per subscriber per campaign/automation mail)
  - name: Links
    description: Tracked links
  - name: Subscriber Imports
    description: Bulk subscriber imports
  - name: Transactional Mails
    description: Transactional email templates and logged sends
  - name: Automation Mails
    description: Reusable emails sent from automation workflows
  - name: Automations
    description: Automation workflows
paths:
  /templates:
    get:
      operationId: listTemplates
      summary: List all templates
      tags:
        - Templates
      parameters:
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `name`, `-name`, `updated_at`, `-updated_at`. Default: `name`.'
          schema:
            type: string
            enum:
              - name
              - -name
              - updated_at
              - -updated_at
        - name: filter[search]
          in: query
          description: Fuzzy search on template name
          schema:
            type: string
      responses:
        '200':
          description: Paginated list of templates
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Template'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      operationId: createTemplate
      summary: Create a template
      tags:
        - Templates
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TemplateRequest'
      responses:
        '201':
          description: Template created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Template'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /templates/{template}:
    get:
      operationId: showTemplate
      summary: Get a template
      tags:
        - Templates
      parameters:
        - name: template
          in: path
          required: true
          description: Template UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Template details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Template'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      operationId: updateTemplate
      summary: Update a template
      tags:
        - Templates
      parameters:
        - name: template
          in: path
          required: true
          description: Template UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TemplateRequest'
      responses:
        '200':
          description: Template updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Template'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
    delete:
      operationId: deleteTemplate
      summary: Delete a template
      tags:
        - Templates
      parameters:
        - name: template
          in: path
          required: true
          description: Template UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /suppressions:
    get:
      operationId: listSuppressions
      summary: List all suppressions
      tags:
        - Suppressions
      parameters:
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `created_at`, `-created_at`.'
          schema:
            type: string
            enum:
              - created_at
              - -created_at
        - name: filter[search]
          in: query
          description: Fuzzy search on email address
          schema:
            type: string
        - name: filter[reason]
          in: query
          description: Filter by exact suppression reason
          schema:
            type: string
      responses:
        '200':
          description: Paginated list of suppressions
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Suppression'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      operationId: createSuppression
      summary: Suppress an email address
      tags:
        - Suppressions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SuppressionRequest'
      responses:
        '201':
          description: Suppression created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Suppression'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /suppressions/{suppression}:
    get:
      operationId: showSuppression
      summary: Get a suppression
      tags:
        - Suppressions
      parameters:
        - name: suppression
          in: path
          required: true
          description: Suppression UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Suppression details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Suppression'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: deleteSuppression
      summary: Remove a suppression
      tags:
        - Suppressions
      parameters:
        - name: suppression
          in: path
          required: true
          description: Suppression UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /email-lists:
    get:
      operationId: listEmailLists
      summary: List all lists
      tags:
        - Lists
      parameters:
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `name`, `-name`, `created_at`, `-created_at`, `active_subscribers_count`, `-active_subscribers_count`. Default: `name`.'
          schema:
            type: string
            enum:
              - name
              - -name
              - created_at
              - -created_at
              - active_subscribers_count
              - -active_subscribers_count
        - name: filter[search]
          in: query
          description: Fuzzy search on list name
          schema:
            type: string
        - name: filter[name]
          in: query
          description: Exact match on list name
          schema:
            type: string
      responses:
        '200':
          description: Paginated list of lists
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/EmailList'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      operationId: createEmailList
      summary: Create a list
      tags:
        - Lists
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EmailListRequest'
      responses:
        '201':
          description: List created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/EmailList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /email-lists/{emailList}:
    get:
      operationId: showEmailList
      summary: Get a list
      tags:
        - Lists
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: List details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/EmailList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      operationId: updateEmailList
      summary: Update a list
      tags:
        - Lists
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EmailListRequest'
      responses:
        '200':
          description: List updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/EmailList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
    delete:
      operationId: deleteEmailList
      summary: Delete a list
      tags:
        - Lists
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /email-lists/{emailList}/tags:
    get:
      operationId: listTags
      summary: List tags for a list
      tags:
        - Tags
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `name`, `-name`, `updated_at`, `-updated_at`, `subscriber_count`, `-subscriber_count`, `visible_in_preferences`, `-visible_in_preferences`. Default: `name`.'
          schema:
            type: string
        - name: filter[search]
          in: query
          description: Fuzzy search on tag name
          schema:
            type: string
        - name: filter[type]
          in: query
          description: Filter by tag type
          schema:
            type: string
        - name: include
          in: query
          description: 'Include related resources. Allowed: `emailList`.'
          schema:
            type: string
            enum:
              - emailList
      responses:
        '200':
          description: Paginated list of tags
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Tag'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      operationId: createTag
      summary: Create a tag
      tags:
        - Tags
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TagRequest'
      responses:
        '201':
          description: Tag created (or existing tag returned if name already exists)
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Tag'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /email-lists/{emailList}/tags/{tag}:
    get:
      operationId: showTag
      summary: Get a tag
      tags:
        - Tags
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
        - name: tag
          in: path
          required: true
          description: Tag UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Tag details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Tag'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      operationId: updateTag
      summary: Update a tag
      tags:
        - Tags
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
        - name: tag
          in: path
          required: true
          description: Tag UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TagRequest'
      responses:
        '200':
          description: Tag updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Tag'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
    delete:
      operationId: deleteTag
      summary: Delete a tag
      tags:
        - Tags
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
        - name: tag
          in: path
          required: true
          description: Tag UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /email-lists/{emailList}/segments:
    get:
      operationId: listSegments
      summary: List segments for a list
      tags:
        - Segments
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `name`, `-name`, `created_at`, `-created_at`. Default: `name`.'
          schema:
            type: string
            enum:
              - name
              - -name
              - created_at
              - -created_at
        - name: filter[search]
          in: query
          description: Fuzzy search on segment name
          schema:
            type: string
        - name: include
          in: query
          description: 'Include related resources. Allowed: `emailList`.'
          schema:
            type: string
            enum:
              - emailList
      responses:
        '200':
          description: Paginated list of segments
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Segment'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      operationId: createSegment
      summary: Create a segment
      tags:
        - Segments
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SegmentRequest'
      responses:
        '201':
          description: Segment created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Segment'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /email-lists/{emailList}/segments/{segment}:
    get:
      operationId: showSegment
      summary: Get a segment
      tags:
        - Segments
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
        - name: segment
          in: path
          required: true
          description: Segment UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Segment details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Segment'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      operationId: updateSegment
      summary: Update a segment
      tags:
        - Segments
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
        - name: segment
          in: path
          required: true
          description: Segment UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SegmentRequest'
      responses:
        '200':
          description: Segment updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Segment'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
    delete:
      operationId: deleteSegment
      summary: Delete a segment
      tags:
        - Segments
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
        - name: segment
          in: path
          required: true
          description: Segment UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /email-lists/{emailList}/subscribers:
    get:
      operationId: listSubscribers
      summary: List subscribers for a list
      tags:
        - Subscribers
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `created_at`, `updated_at`, `subscribed_at`, `unsubscribed_at`, `email`, `first_name`, `last_name`, `id` (prefix with `-` for descending).'
          schema:
            type: string
        - name: filter[email]
          in: query
          description: Exact match on email address
          schema:
            type: string
        - name: filter[status]
          in: query
          description: Filter by subscription status
          schema:
            type: string
            enum:
              - subscribed
              - unsubscribed
              - unconfirmed
        - name: filter[search]
          in: query
          description: Search across email, first name, and last name
          schema:
            type: string
        - name: filter[tags]
          in: query
          description: Filter by tag names or UUIDs (comma-separated)
          schema:
            type: string
        - name: filter[tagType]
          in: query
          description: 'How to combine tag filters: `any` (default) or `all`'
          schema:
            type: string
            enum:
              - any
              - all
        - name: filter[segment_uuid]
          in: query
          description: Filter by segment UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Paginated list of subscribers
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Subscriber'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
    post:
      operationId: createSubscriber
      summary: Subscribe an email address to a list
      tags:
        - Subscribers
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StoreSubscriberRequest'
      responses:
        '201':
          description: Subscriber created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Subscriber'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /email-lists/{emailList}/confirm:
    post:
      operationId: confirmSubscriberByList
      summary: Confirm a subscriber by list
      tags:
        - Subscribers
      description: Confirm an unconfirmed subscriber. Provide the subscriber's email in the request body.
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriberEmailRequest'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /email-lists/{emailList}/unsubscribe:
    post:
      operationId: unsubscribeByList
      summary: Unsubscribe a subscriber by list
      tags:
        - Subscribers
      description: Unsubscribe a currently subscribed subscriber. Provide the subscriber's email in the request body.
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriberEmailRequest'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /email-lists/{emailList}/resubscribe:
    post:
      operationId: resubscribeByList
      summary: Resubscribe a subscriber by list
      tags:
        - Subscribers
      description: Resubscribe a previously unsubscribed subscriber. Provide the subscriber's email in the request body.
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriberEmailRequest'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /email-lists/{emailList}/resend-confirmation:
    post:
      operationId: resendConfirmationByList
      summary: Resend confirmation mail by list
      tags:
        - Subscribers
      description: Resend the confirmation email to an unconfirmed subscriber. Provide the subscriber's email in the request body.
      parameters:
        - name: emailList
          in: path
          required: true
          description: Email list UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriberEmailRequest'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /subscribers/{subscriber}:
    get:
      operationId: showSubscriber
      summary: Get a subscriber
      tags:
        - Subscribers
      parameters:
        - name: subscriber
          in: path
          required: true
          description: Subscriber UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Subscriber details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Subscriber'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      operationId: updateSubscriber
      summary: Update a subscriber
      tags:
        - Subscribers
      parameters:
        - name: subscriber
          in: path
          required: true
          description: Subscriber UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSubscriberRequest'
      responses:
        '200':
          description: Subscriber updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Subscriber'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
    delete:
      operationId: deleteSubscriber
      summary: Delete a subscriber
      tags:
        - Subscribers
      parameters:
        - name: subscriber
          in: path
          required: true
          description: Subscriber UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /subscribers/{subscriber}/confirm:
    post:
      operationId: confirmSubscriber
      summary: Confirm a subscriber
      tags:
        - Subscribers
      parameters:
        - name: subscriber
          in: path
          required: true
          description: Subscriber UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /subscribers/{subscriber}/unsubscribe:
    post:
      operationId: unsubscribeSubscriber
      summary: Unsubscribe a subscriber
      tags:
        - Subscribers
      parameters:
        - name: subscriber
          in: path
          required: true
          description: Subscriber UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /subscribers/{subscriber}/resubscribe:
    post:
      operationId: resubscribeSubscriber
      summary: Resubscribe a subscriber
      tags:
        - Subscribers
      parameters:
        - name: subscriber
          in: path
          required: true
          description: Subscriber UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /subscribers/{subscriber}/resend-confirmation:
    post:
      operationId: resendConfirmation
      summary: Resend confirmation mail
      tags:
        - Subscribers
      parameters:
        - name: subscriber
          in: path
          required: true
          description: Subscriber UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /subscribers/{subscriber}/tags:
    post:
      operationId: addSubscriberTags
      summary: Add tags to a subscriber
      tags:
        - Subscribers
      parameters:
        - name: subscriber
          in: path
          required: true
          description: Subscriber UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriberTagsRequest'
      responses:
        '200':
          description: Updated subscriber with tags
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Subscriber'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
    delete:
      operationId: removeSubscriberTags
      summary: Remove tags from a subscriber
      tags:
        - Subscribers
      parameters:
        - name: subscriber
          in: path
          required: true
          description: Subscriber UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriberTagsRequest'
      responses:
        '200':
          description: Updated subscriber with tags removed
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Subscriber'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /campaigns:
    get:
      operationId: listCampaigns
      summary: List all campaigns
      tags:
        - Campaigns
      parameters:
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `name`, `-name`, `email_list_id`, `unique_open_count`, `unique_click_count`, `unsubscribe_rate`, `sent_to_number_of_subscribers`, `sent`, `-sent` (default: `-sent`).'
          schema:
            type: string
        - name: filter[search]
          in: query
          description: Fuzzy search on campaign name
          schema:
            type: string
        - name: filter[status]
          in: query
          description: Filter by campaign status
          schema:
            type: string
            enum:
              - draft
              - sending
              - paused
              - sent
              - cancelled
        - name: filter[email_list_id]
          in: query
          description: Filter by list ID
          schema:
            type: integer
        - name: filter[emailList.uuid]
          in: query
          description: Filter by list UUID
          schema:
            type: string
            format: uuid
        - name: filter[contentItem.template.uuid]
          in: query
          description: Filter by template UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Paginated list of campaigns
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Campaign'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      operationId: createCampaign
      summary: Create a campaign
      description: Scheduling is rejected with a 422 response when the selected segment contains unavailable list exclusions.
      tags:
        - Campaigns
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CampaignRequest'
      responses:
        '201':
          description: Campaign created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Campaign'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /campaigns/{campaign}:
    get:
      operationId: showCampaign
      summary: Get a campaign
      tags:
        - Campaigns
      parameters:
        - name: campaign
          in: path
          required: true
          description: Campaign UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Campaign details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Campaign'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      operationId: updateCampaign
      summary: Update a campaign
      description: Scheduling is rejected with a 422 response when the selected segment contains unavailable list exclusions.
      tags:
        - Campaigns
      parameters:
        - name: campaign
          in: path
          required: true
          description: Campaign UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CampaignRequest'
      responses:
        '200':
          description: Campaign updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Campaign'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
    delete:
      operationId: deleteCampaign
      summary: Delete a campaign
      tags:
        - Campaigns
      parameters:
        - name: campaign
          in: path
          required: true
          description: Campaign UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /campaigns/{campaign}/send-test:
    post:
      operationId: sendCampaignTest
      summary: Send a test email for a campaign
      tags:
        - Campaigns
      description: Send a test email to up to 10 recipients. Campaign must be in draft status.
      parameters:
        - name: campaign
          in: path
          required: true
          description: Campaign UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendCampaignTestRequest'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /campaigns/{campaign}/send:
    post:
      operationId: sendCampaign
      summary: Send a campaign
      tags:
        - Campaigns
      description: Start sending the campaign to all subscribers. Campaign must be in draft status.
      parameters:
        - name: campaign
          in: path
          required: true
          description: Campaign UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '400':
          description: Campaign cannot be sent (e.g. already sent, missing content)
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /campaigns/{campaign}/pause:
    post:
      operationId: pauseCampaign
      summary: Pause a campaign
      tags:
        - Campaigns
      description: Pause a campaign that is currently sending. Pausing an already paused campaign is idempotent.
      parameters:
        - name: campaign
          in: path
          required: true
          description: Campaign UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Campaign cannot be paused from its current status
  /campaigns/{campaign}/resume:
    post:
      operationId: resumeCampaign
      summary: Resume a campaign
      tags:
        - Campaigns
      description: Resume a paused campaign. Resuming a campaign that is already sending is idempotent.
      parameters:
        - name: campaign
          in: path
          required: true
          description: Campaign UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Campaign cannot be resumed from its current status or has an invalid segment
  /campaigns/{campaign}/opens:
    get:
      operationId: listCampaignOpens
      summary: List campaign opens
      tags:
        - Campaign Statistics
      parameters:
        - name: campaign
          in: path
          required: true
          description: Campaign UUID
          schema:
            type: string
            format: uuid
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `email`, `open_count`, `first_opened_at`, `-first_opened_at` (default), `last_opened_at`.'
          schema:
            type: string
        - name: filter[search]
          in: query
          description: Fuzzy search on subscriber email
          schema:
            type: string
      responses:
        '200':
          description: Paginated list of opens grouped by subscriber
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Open'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /campaigns/{campaign}/clicks:
    get:
      operationId: listCampaignClicks
      summary: List campaign link clicks
      tags:
        - Campaign Statistics
      parameters:
        - name: campaign
          in: path
          required: true
          description: Campaign UUID
          schema:
            type: string
            format: uuid
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `unique_click_count`, `-unique_click_count` (default), `click_count`.'
          schema:
            type: string
        - name: filter[search]
          in: query
          description: Fuzzy search on link URL
          schema:
            type: string
      responses:
        '200':
          description: Paginated list of tracked links with click data
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Link'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /campaigns/{campaign}/unsubscribes:
    get:
      operationId: listCampaignUnsubscribes
      summary: List campaign unsubscribes
      tags:
        - Campaign Statistics
      parameters:
        - name: campaign
          in: path
          required: true
          description: Campaign UUID
          schema:
            type: string
            format: uuid
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `created_at`, `-created_at` (default).'
          schema:
            type: string
        - name: filter[search]
          in: query
          description: Fuzzy search on subscriber email, first name, or last name
          schema:
            type: string
      responses:
        '200':
          description: Paginated list of unsubscribes
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/CampaignUnsubscribe'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /campaigns/{campaign}/bounces:
    get:
      operationId: listCampaignBounces
      summary: List campaign bounces
      tags:
        - Campaign Statistics
      parameters:
        - name: campaign
          in: path
          required: true
          description: Campaign UUID
          schema:
            type: string
            format: uuid
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `email`, `bounce_count`, `created_at`, `-created_at` (default).'
          schema:
            type: string
        - name: filter[search]
          in: query
          description: Fuzzy search on subscriber email
          schema:
            type: string
        - name: filter[type]
          in: query
          description: Filter by bounce type
          schema:
            type: string
      responses:
        '200':
          description: Paginated list of bounces grouped by subscriber
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Bounce'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /sends:
    get:
      operationId: listSends
      summary: List all sends
      tags:
        - Sends
      parameters:
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `sent_at`, `-sent_at` (default).'
          schema:
            type: string
            enum:
              - sent_at
              - -sent_at
        - name: filter[subscriber_uuid]
          in: query
          description: Filter by subscriber UUID
          schema:
            type: string
            format: uuid
        - name: filter[campaign_uuid]
          in: query
          description: Filter by campaign UUID
          schema:
            type: string
            format: uuid
        - name: filter[automation_mail_uuid]
          in: query
          description: Filter by automation mail UUID
          schema:
            type: string
            format: uuid
        - name: filter[transactional_mail_log_item_uuid]
          in: query
          description: Filter by transactional mail log item UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Paginated list of sends
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Send'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /sends/{send}:
    get:
      operationId: showSend
      summary: Get a send
      tags:
        - Sends
      parameters:
        - name: send
          in: path
          required: true
          description: Send UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Send details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Send'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: deleteSend
      summary: Delete a send
      tags:
        - Sends
      parameters:
        - name: send
          in: path
          required: true
          description: Send UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /links/{link}:
    get:
      operationId: showLink
      summary: Get a tracked link
      tags:
        - Links
      parameters:
        - name: link
          in: path
          required: true
          description: Link UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Link details with clicks
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Link'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /subscriber-imports:
    get:
      operationId: listSubscriberImports
      summary: List all subscriber imports
      tags:
        - Subscriber Imports
      parameters:
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `created_at`, `-created_at` (default), `status`, `-status`.'
          schema:
            type: string
        - name: filter[email_list_uuid]
          in: query
          description: Filter by list UUID
          schema:
            type: string
            format: uuid
        - name: filter[status]
          in: query
          description: Filter by import status
          schema:
            type: string
      responses:
        '200':
          description: Paginated list of subscriber imports
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/SubscriberImportIndex'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      operationId: createSubscriberImport
      summary: Create a subscriber import
      tags:
        - Subscriber Imports
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriberImportRequest'
      responses:
        '201':
          description: Subscriber import created in draft status
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/SubscriberImport'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /subscriber-imports/{subscriberImport}:
    get:
      operationId: showSubscriberImport
      summary: Get a subscriber import
      tags:
        - Subscriber Imports
      parameters:
        - name: subscriberImport
          in: path
          required: true
          description: Subscriber import UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Subscriber import details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/SubscriberImport'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      operationId: updateSubscriberImport
      summary: Update a subscriber import
      tags:
        - Subscriber Imports
      description: Can only update imports in draft status.
      parameters:
        - name: subscriberImport
          in: path
          required: true
          description: Subscriber import UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriberImportRequest'
      responses:
        '200':
          description: Subscriber import updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/SubscriberImport'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
    delete:
      operationId: deleteSubscriberImport
      summary: Delete a subscriber import
      tags:
        - Subscriber Imports
      parameters:
        - name: subscriberImport
          in: path
          required: true
          description: Subscriber import UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /subscriber-imports/{subscriberImport}/append:
    post:
      operationId: appendSubscriberImport
      summary: Append CSV data to an import
      tags:
        - Subscriber Imports
      description: Append additional CSV rows to an existing subscriber import.
      parameters:
        - name: subscriberImport
          in: path
          required: true
          description: Subscriber import UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AppendSubscriberImportRequest'
      responses:
        '200':
          description: Updated subscriber import
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/SubscriberImport'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /subscriber-imports/{subscriberImport}/start:
    post:
      operationId: startSubscriberImport
      summary: Start processing a subscriber import
      tags:
        - Subscriber Imports
      description: |
        Starts the import job. The import must be in draft status.
        The CSV must have an `email` header column.
      parameters:
        - name: subscriberImport
          in: path
          required: true
          description: Subscriber import UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /transactional-mails:
    get:
      operationId: listTransactionalMails
      summary: List transactional mail log items
      tags:
        - Transactional Mails
      parameters:
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `subject`, `created_at`, `-created_at` (default).'
          schema:
            type: string
        - name: filter[search]
          in: query
          description: Fuzzy search on subject
          schema:
            type: string
        - name: filter[transport_message_id]
          in: query
          description: Filter by transport message ID
          schema:
            type: string
      responses:
        '200':
          description: Paginated list of transactional mail log items
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/TransactionalMailLogItem'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /transactional-mails/send:
    post:
      operationId: sendTransactionalMail
      summary: Send a transactional mail
      tags:
        - Transactional Mails
      description: |
        Send a transactional email. You can either reference a stored template
        via `mail_name`, or provide `subject` and `html`/`text` directly.
        Send permission is checked for all recipients, including template recipients, CC, and BCC.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendTransactionalMailRequest'
      responses:
        '200':
          description: Mail sent and stored — returns the log item UUID
          content:
            application/json:
              schema:
                type: object
                properties:
                  uuid:
                    type: string
                    format: uuid
        '204':
          description: Mail sent but not stored (store=false)
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '406':
          description: Email address is suppressed or invalid
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '500':
          description: Internal server error while sending
  /transactional-mails/templates:
    get:
      operationId: listTransactionalMailTemplates
      summary: List transactional mail templates
      tags:
        - Transactional Mails
      parameters:
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `subject`, `created_at`, `-created_at` (default).'
          schema:
            type: string
        - name: filter[search]
          in: query
          description: Fuzzy search on subject and name
          schema:
            type: string
        - name: filter[uuid]
          in: query
          description: Exact match on UUID
          schema:
            type: string
            format: uuid
        - name: filter[name]
          in: query
          description: Exact match on name
          schema:
            type: string
      responses:
        '200':
          description: Paginated list of transactional mail templates
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/TransactionalMail'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /transactional-mails/templates/{transactionalMailTemplate}:
    get:
      operationId: showTransactionalMailTemplate
      summary: Get a transactional mail template
      tags:
        - Transactional Mails
      parameters:
        - name: transactionalMailTemplate
          in: path
          required: true
          description: Transactional mail template UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Transactional mail template details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/TransactionalMail'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /transactional-mails/{transactionalMail}:
    get:
      operationId: showTransactionalMailLogItem
      summary: Get a transactional mail log item
      tags:
        - Transactional Mails
      parameters:
        - name: transactionalMail
          in: path
          required: true
          description: Transactional mail log item UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Transactional mail log item details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/TransactionalMailLogItem'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /transactional-mails/{transactionalMail}/resend:
    post:
      operationId: resendTransactionalMail
      summary: Resend a transactional mail
      description: Resends to the original recipients. Addresses on the suppression list cannot receive resends.
      tags:
        - Transactional Mails
      parameters:
        - name: transactionalMail
          in: path
          required: true
          description: Transactional mail log item UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '406':
          description: A recipient is on the suppression list.
  /automation-mails:
    get:
      operationId: listAutomationMails
      summary: List all automation mails
      tags:
        - Automation Mails
      parameters:
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: sort
          in: query
          description: 'Sort field. Allowed: `name`, `-name`, `created_at`, `-created_at` (default: `-created_at`).'
          schema:
            type: string
        - name: filter[search]
          in: query
          description: Fuzzy search on name and subject
          schema:
            type: string
        - name: filter[name]
          in: query
          description: Filter by exact name
          schema:
            type: string
        - name: filter[uuid]
          in: query
          description: Filter by exact UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Paginated list of automation mails
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/AutomationMail'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      operationId: createAutomationMail
      summary: Create an automation mail
      tags:
        - Automation Mails
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AutomationMailRequest'
      responses:
        '201':
          description: Automation mail created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/AutomationMail'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
  /automation-mails/{automationMail}:
    get:
      operationId: showAutomationMail
      summary: Get an automation mail
      tags:
        - Automation Mails
      parameters:
        - name: automationMail
          in: path
          required: true
          description: Automation mail UUID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Automation mail details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/AutomationMail'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      operationId: updateAutomationMail
      summary: Update an automation mail
      tags:
        - Automation Mails
      parameters:
        - name: automationMail
          in: path
          required: true
          description: Automation mail UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AutomationMailRequest'
      responses:
        '200':
          description: Automation mail updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/AutomationMail'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
    delete:
      operationId: deleteAutomationMail
      summary: Delete an automation mail
      tags:
        - Automation Mails
      parameters:
        - name: automationMail
          in: path
          required: true
          description: Automation mail UUID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /automations/{automation}/trigger:
    post:
      operationId: triggerAutomation
      summary: Trigger an automation via webhook
      tags:
        - Automations
      description: |
        Trigger an automation's webhook trigger for a list of subscribers.
        The automation must have at least one Webhook trigger configured.
      parameters:
        - name: automation
          in: path
          required: true
          description: Automation UUID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TriggerAutomationRequest'
      responses:
        '200':
          description: Automation triggered successfully
        '400':
          description: Automation does not have a Webhook trigger
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: Laravel Sanctum API token
  parameters:
    page:
      name: page
      in: query
      description: Page number
      schema:
        type: integer
        minimum: 1
        default: 1
    per_page:
      name: per_page
      in: query
      description: Number of items per page
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 15
  schemas:
    Uuid:
      type: string
      format: uuid
      example: 00000000-0000-0000-0000-000000000000
    Timestamp:
      type: string
      format: date-time
      example: '2026-01-15T12:00:00.000000Z'
    Template:
      type: object
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        name:
          type: string
          example: Monthly newsletter
        html:
          type: string
          nullable: true
          description: Compiled HTML content
        fields:
          type: object
          nullable: true
          description: Template field values (editor-specific)
          additionalProperties: true
        structured_html:
          type: string
          nullable: true
          description: Structured HTML used by the editor
        created_at:
          $ref: '#/components/schemas/Timestamp'
        updated_at:
          $ref: '#/components/schemas/Timestamp'
    PaginationLinks:
      type: object
      properties:
        first:
          type: string
          format: uri
          example: https://your-app.com/api/templates?page=1
        last:
          type: string
          format: uri
          example: https://your-app.com/api/templates?page=5
        prev:
          type: string
          format: uri
          nullable: true
        next:
          type: string
          format: uri
          nullable: true
    PaginationMeta:
      type: object
      properties:
        current_page:
          type: integer
          example: 1
        from:
          type: integer
          nullable: true
          example: 1
        last_page:
          type: integer
          example: 5
        links:
          type: array
          items:
            type: object
            properties:
              url:
                type: string
                format: uri
                nullable: true
              label:
                type: string
              active:
                type: boolean
        path:
          type: string
          format: uri
        per_page:
          type: integer
          example: 15
        to:
          type: integer
          nullable: true
          example: 15
        total:
          type: integer
          example: 73
    TemplateRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          example: Monthly newsletter
        html:
          type: string
          nullable: true
        structured_html:
          type: string
          nullable: true
    ValidationError:
      type: object
      properties:
        message:
          type: string
          example: The given data was invalid.
        errors:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
      required:
        - message
        - errors
    Suppression:
      type: object
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        email:
          type: string
          format: email
          example: suppressed@example.com
        reason:
          type: string
          nullable: true
          description: Reason for suppression (e.g. bounce, complaint, manual)
        created_at:
          $ref: '#/components/schemas/Timestamp'
        updated_at:
          $ref: '#/components/schemas/Timestamp'
    SuppressionRequest:
      type: object
      required:
        - email
      properties:
        email:
          type: string
          format: email
          example: suppress@example.com
    EmailList:
      type: object
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        name:
          type: string
          example: Newsletter subscribers
        active_subscribers_count:
          type: integer
          example: 1234
        campaigns_feed_enabled:
          type: boolean
        default_from_email:
          type: string
          format: email
        default_from_name:
          type: string
          nullable: true
        default_reply_to_email:
          type: string
          nullable: true
        default_reply_to_name:
          type: string
          nullable: true
        allow_form_subscriptions:
          type: boolean
        honeypot_field:
          type: string
          nullable: true
        redirect_after_subscribed:
          type: string
          nullable: true
        redirect_after_already_subscribed:
          type: string
          nullable: true
        redirect_after_subscription_pending:
          type: string
          nullable: true
        redirect_after_unsubscribed:
          type: string
          nullable: true
        requires_confirmation:
          type: boolean
        confirmation_mailable_class:
          type: string
          nullable: true
        campaign_mailer:
          type: string
          nullable: true
        automation_mailer:
          type: string
          nullable: true
        transactional_mailer:
          type: string
          nullable: true
        report_recipients:
          type: string
          nullable: true
        report_campaign_sent:
          type: boolean
        report_campaign_summary:
          type: boolean
        report_email_list_summary:
          type: boolean
        email_list_summary_sent_at:
          $ref: '#/components/schemas/Timestamp'
        created_at:
          $ref: '#/components/schemas/Timestamp'
        updated_at:
          $ref: '#/components/schemas/Timestamp'
    EmailListRequest:
      type: object
      required:
        - name
        - default_from_email
      properties:
        name:
          type: string
        default_from_email:
          type: string
          format: email
        default_from_name:
          type: string
        default_reply_to_email:
          type: string
          description: Comma-delimited list of reply-to email addresses
        default_reply_to_name:
          type: string
        extra_attributes:
          type: object
          nullable: true
          additionalProperties: true
        campaigns_feed_enabled:
          type: boolean
        report_campaign_sent:
          type: boolean
        report_campaign_summary:
          type: boolean
        report_email_list_summary:
          type: boolean
        report_recipients:
          type: string
          description: Comma-delimited list of report recipient emails
        campaign_mailer:
          type: string
        automation_mailer:
          type: string
        transactional_mailer:
          type: string
        allow_form_subscriptions:
          type: boolean
        allowed_form_extra_attributes:
          type: string
        requires_confirmation:
          type: boolean
        allowed_form_subscription_tags:
          type: array
          items:
            type: string
        honeypot_field:
          type: string
          nullable: true
        redirect_after_subscribed:
          type: string
        redirect_after_already_subscribed:
          type: string
        redirect_after_subscription_pending:
          type: string
        redirect_after_unsubscribed:
          type: string
        confirmation_mail:
          type: string
          enum:
            - send_default_confirmation_mail
            - send_custom_confirmation_mail
        confirmation_mail_uuid:
          type: string
          format: uuid
          description: Required when confirmation_mail is `send_custom_confirmation_mail`
    Tag:
      type: object
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        name:
          type: string
          example: vip
        email_list:
          $ref: '#/components/schemas/EmailList'
        email_list_uuid:
          $ref: '#/components/schemas/Uuid'
        created_at:
          $ref: '#/components/schemas/Timestamp'
        updated_at:
          $ref: '#/components/schemas/Timestamp'
    TagRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          example: vip
        visible_in_preferences:
          type: boolean
          nullable: true
    Segment:
      type: object
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        name:
          type: string
          example: Active VIPs
        positive_tags:
          type: array
          items:
            type: string
          description: Tag names the subscriber must have. Empty when the segment has no positive tag condition.
          example:
            - vip
        negative_tags:
          type: array
          items:
            type: string
          description: Tag names the subscriber must not have. Empty when the segment has no negative tag condition.
          example:
            - churned
        all_positive_tags_required:
          type: boolean
          description: When true, the subscriber must have ALL positive tags (AND). When false, ANY tag matches (OR).
        all_negative_tags_required:
          type: boolean
          description: When true, the subscriber must lack ALL negative tags. When false, lacking ANY tag excludes them.
        email_list:
          $ref: '#/components/schemas/EmailList'
        email_list_uuid:
          $ref: '#/components/schemas/Uuid'
        created_at:
          $ref: '#/components/schemas/Timestamp'
        updated_at:
          $ref: '#/components/schemas/Timestamp'
    SegmentRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          example: Active VIPs
        all_positive_tags_required:
          type: boolean
          description: When true, subscriber must have ALL positive tags (AND). When false, ANY tag matches (OR).
        all_negative_tags_required:
          type: boolean
          description: When true, subscriber must lack ALL negative tags. When false, lacking ANY tag excludes them.
        positive_tags:
          type: array
          nullable: true
          items:
            type: string
          description: Tag names the subscriber must have
        negative_tags:
          type: array
          nullable: true
          items:
            type: string
          description: Tag names the subscriber must not have
    Subscriber:
      type: object
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        email_list_uuid:
          $ref: '#/components/schemas/Uuid'
        email:
          type: string
          format: email
          example: john@example.com
        first_name:
          type: string
          nullable: true
          example: John
        last_name:
          type: string
          nullable: true
          example: Doe
        extra_attributes:
          type: object
          additionalProperties: true
        tags:
          type: array
          items:
            type: string
          example:
            - newsletter
            - vip
        subscribed_at:
          $ref: '#/components/schemas/Timestamp'
        unsubscribed_at:
          type: string
          format: date-time
          nullable: true
        created_at:
          $ref: '#/components/schemas/Timestamp'
        updated_at:
          $ref: '#/components/schemas/Timestamp'
    StoreSubscriberRequest:
      type: object
      required:
        - email
      properties:
        email:
          type: string
          format: email
        first_name:
          type: string
          nullable: true
        last_name:
          type: string
          nullable: true
        extra_attributes:
          type: object
          nullable: true
          additionalProperties: true
        tags:
          type: array
          nullable: true
          items:
            type: string
        skip_confirmation:
          type: boolean
          description: Skip double opt-in confirmation
        strict:
          type: boolean
          description: When true, fails if subscriber already exists on this list
    SubscriberEmailRequest:
      type: object
      required:
        - email
      properties:
        email:
          type: string
          format: email
          description: Email address of the subscriber
    UpdateSubscriberRequest:
      type: object
      properties:
        email:
          type: string
          format: email
        first_name:
          type: string
          nullable: true
        last_name:
          type: string
          nullable: true
        extra_attributes:
          type: object
          nullable: true
          additionalProperties: true
        tags:
          type: array
          items:
            type: string
        append_tags:
          type: boolean
          description: When true, tags are appended instead of replaced
    SubscriberTagsRequest:
      type: object
      required:
        - tags
      properties:
        tags:
          type: array
          items:
            type: string
    Campaign:
      type: object
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        name:
          type: string
          example: March 2026 Newsletter
        email_list_uuid:
          $ref: '#/components/schemas/Uuid'
        email_list:
          $ref: '#/components/schemas/EmailList'
        template_uuid:
          type: string
          format: uuid
          nullable: true
        template:
          $ref: '#/components/schemas/Template'
        from_email:
          type: string
          format: email
          nullable: true
        from_name:
          type: string
          nullable: true
        status:
          type: string
          example: draft
        html:
          type: string
          nullable: true
        structured_html:
          type: string
          nullable: true
        email_html:
          type: string
          nullable: true
          description: Final rendered HTML sent to subscribers
        webview_html:
          type: string
          nullable: true
        fields:
          type: object
          nullable: true
          additionalProperties: true
          description: Template field values
        mailable_class:
          type: string
          nullable: true
        utm_tags:
          type: boolean
          nullable: true
        sent_to_number_of_subscribers:
          type: integer
        segment_uuid:
          type: string
          format: uuid
          nullable: true
        segment_class:
          type: string
          nullable: true
        segment_description:
          type: string
          nullable: true
        open_count:
          type: integer
        unique_open_count:
          type: integer
        open_rate:
          type: number
          format: float
        click_count:
          type: integer
        unique_click_count:
          type: integer
        click_rate:
          type: number
          format: float
        unsubscribe_count:
          type: integer
        unsubscribe_rate:
          type: number
          format: float
        bounce_count:
          type: integer
        bounce_rate:
          type: number
          format: float
        sent_at:
          type: string
          format: date-time
          nullable: true
        statistics_calculated_at:
          type: string
          format: date-time
          nullable: true
        scheduled_at:
          type: string
          format: date-time
          nullable: true
        summary_mail_sent_at:
          type: string
          format: date-time
          nullable: true
        created_at:
          $ref: '#/components/schemas/Timestamp'
        updated_at:
          $ref: '#/components/schemas/Timestamp'
    CampaignRequest:
      type: object
      required:
        - name
        - email_list_uuid
      properties:
        name:
          type: string
        subject:
          type: string
          nullable: true
        type:
          type: string
          enum:
            - draft
          nullable: true
        email_list_uuid:
          type: string
          format: uuid
        segment_uuid:
          type: string
          format: uuid
          nullable: true
        template_uuid:
          type: string
          format: uuid
          description: UUID of the template to use
        html:
          type: string
          nullable: true
        fields:
          type: object
          nullable: true
          additionalProperties: true
        mailable_class:
          type: string
          nullable: true
        utm_tags:
          type: boolean
          nullable: true
        add_subscriber_tags:
          type: boolean
          nullable: true
        add_subscriber_link_tags:
          type: boolean
          nullable: true
        disable_webview:
          type: boolean
          nullable: true
        schedule_at:
          type: string
          description: 'Format: Y-m-d H:i:s'
          example: '2026-03-15 10:00:00'
    SendCampaignTestRequest:
      type: object
      required:
        - email
      properties:
        email:
          type: string
          description: Comma-delimited list of email addresses (max 10)
          example: test@example.com
    Open:
      type: object
      properties:
        subscriber_uuid:
          $ref: '#/components/schemas/Uuid'
        subscriber_email_list_uuid:
          $ref: '#/components/schemas/Uuid'
        subscriber_email:
          type: string
          format: email
        open_count:
          type: integer
        first_opened_at:
          $ref: '#/components/schemas/Timestamp'
        last_opened_at:
          $ref: '#/components/schemas/Timestamp'
    Click:
      type: object
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        send_uuid:
          $ref: '#/components/schemas/Uuid'
        link_uuid:
          $ref: '#/components/schemas/Uuid'
        subscriber_uuid:
          type: string
          format: uuid
          nullable: true
        created_at:
          $ref: '#/components/schemas/Timestamp'
        updated_at:
          $ref: '#/components/schemas/Timestamp'
    Link:
      type: object
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        url:
          type: string
          format: uri
        unique_click_count:
          type: integer
        click_count:
          type: integer
        clicks:
          type: array
          items:
            $ref: '#/components/schemas/Click'
    CampaignUnsubscribe:
      type: object
      properties:
        campaign_uuid:
          $ref: '#/components/schemas/Uuid'
        campaign:
          $ref: '#/components/schemas/Campaign'
        subscriber_uuid:
          $ref: '#/components/schemas/Uuid'
        subscriber_email:
          type: string
          format: email
        subscriber:
          $ref: '#/components/schemas/Subscriber'
    Bounce:
      type: object
      properties:
        subscriber_uuid:
          $ref: '#/components/schemas/Uuid'
        subscriber_email_list_uuid:
          $ref: '#/components/schemas/Uuid'
        subscriber_email:
          type: string
          format: email
        bounce_count:
          type: integer
        type:
          type: string
        created_at:
          $ref: '#/components/schemas/Timestamp'
    Send:
      type: object
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        transport_message_id:
          type: string
          nullable: true
        campaign_uuid:
          type: string
          format: uuid
          nullable: true
        automation_mail_uuid:
          type: string
          format: uuid
          nullable: true
        transactional_mail_log_item_uuid:
          type: string
          format: uuid
          nullable: true
        content_item_name:
          type: string
          nullable: true
          description: Name of the campaign, automation mail, or transactional mail
        subscriber_uuid:
          type: string
          format: uuid
          nullable: true
        subscriber_email:
          type: string
          format: email
          nullable: true
        sent_at:
          type: string
          format: date-time
          nullable: true
        failed_at:
          type: string
          format: date-time
          nullable: true
        failure_reason:
          type: string
          nullable: true
        open_count:
          type: integer
        click_count:
          type: integer
        bounce_count:
          type: integer
        hard_bounce_count:
          type: integer
        soft_bounce_count:
          type: integer
        first_opened_at:
          type: string
          format: date-time
          nullable: true
        last_opened_at:
          type: string
          format: date-time
          nullable: true
        first_clicked_at:
          type: string
          format: date-time
          nullable: true
        last_clicked_at:
          type: string
          format: date-time
          nullable: true
        created_at:
          $ref: '#/components/schemas/Timestamp'
        updated_at:
          $ref: '#/components/schemas/Timestamp'
    SubscriberImportIndex:
      type: object
      description: Simplified representation used in list endpoints (excludes subscribers_csv)
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        status:
          type: string
        email_list_uuid:
          $ref: '#/components/schemas/Uuid'
        subscribe_unsubscribed:
          type: boolean
        unsubscribe_others:
          type: boolean
        replace_tags:
          type: boolean
        imported_subscribers_count:
          type: integer
        error_count:
          type: integer
    SubscriberImportRequest:
      type: object
      required:
        - subscribers_csv
        - email_list_uuid
      properties:
        subscribers_csv:
          type: string
          description: CSV content with at least an `email` header column
        email_list_uuid:
          type: string
          format: uuid
        subscribe_unsubscribed:
          type: boolean
          description: Re-subscribe previously unsubscribed subscribers
        unsubscribe_others:
          type: boolean
          description: Unsubscribe subscribers not in the import
        replace_tags:
          type: boolean
          description: Replace existing tags with imported tags
    SubscriberImport:
      type: object
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        subscribers_csv:
          type: string
          nullable: true
          description: CSV content of subscribers to import
        status:
          type: string
          example: draft
        email_list_uuid:
          $ref: '#/components/schemas/Uuid'
        subscribe_unsubscribed:
          type: boolean
        unsubscribe_others:
          type: boolean
        replace_tags:
          type: boolean
        imported_subscribers_count:
          type: integer
        error_count:
          type: integer
        created_at:
          $ref: '#/components/schemas/Timestamp'
    AppendSubscriberImportRequest:
      type: object
      required:
        - subscribers_csv
      properties:
        subscribers_csv:
          type: string
          description: Additional CSV rows to append to the import
    TransactionalMailLogItem:
      type: object
      description: A logged transactional mail send
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        subject:
          type: string
        from:
          type: string
        to:
          type: array
          items:
            type: string
        cc:
          type: array
          nullable: true
          items:
            type: string
        bcc:
          type: array
          nullable: true
          items:
            type: string
        body:
          type: string
          description: HTML content of the sent mail
        html:
          type: string
          description: HTML content of the sent mail (alias of body)
        created_at:
          $ref: '#/components/schemas/Timestamp'
    SendTransactionalMailRequest:
      type: object
      required:
        - from
        - to
      properties:
        mail_name:
          type: string
          description: Name or UUID of an existing transactional mail template. Unknown names and UUIDs return a validation error.
        subject:
          type: string
          nullable: true
          description: Required when mail_name is not provided
        html:
          type: string
          nullable: true
          description: Required when mail_name and text are not provided
        text:
          type: string
          nullable: true
          description: Required when mail_name and html are not provided
        replacements:
          type: object
          nullable: true
          additionalProperties: true
          description: Key-value replacements for template placeholders
        from:
          type: string
          description: Sender email address (or "Name <email>" format)
        to:
          type: string
          description: Comma-delimited list of recipient addresses
        cc:
          type: string
          nullable: true
          description: Comma-delimited list of CC addresses
        bcc:
          type: string
          nullable: true
          description: Comma-delimited list of BCC addresses
        reply_to:
          type: string
          nullable: true
          description: Comma-delimited list of reply-to addresses
        store:
          type: boolean
          description: Whether to store the sent mail as a log item (default true)
        mailer:
          type: string
          description: Mailer config key to use
        attachments:
          type: array
          nullable: true
          items:
            type: object
            required:
              - name
              - content
              - content_type
            properties:
              name:
                type: string
              content:
                type: string
                description: Base64-encoded file content
              content_type:
                type: string
                example: application/pdf
              content_id:
                type: string
                nullable: true
                description: Content-ID for inline attachments
        fake:
          type: boolean
          description: When true, mail is not actually sent
    TransactionalMail:
      type: object
      description: Transactional mail template
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        name:
          type: string
          example: order-confirmation
        to:
          type: array
          nullable: true
          items:
            type: string
        cc:
          type: array
          nullable: true
          items:
            type: string
        bcc:
          type: array
          nullable: true
          items:
            type: string
        subject:
          type: string
        html:
          type: string
        store_mail:
          type: boolean
        created_at:
          $ref: '#/components/schemas/Timestamp'
    AutomationMail:
      type: object
      properties:
        uuid:
          $ref: '#/components/schemas/Uuid'
        name:
          type: string
          example: Welcome email
        template_uuid:
          type: string
          format: uuid
          nullable: true
        template:
          $ref: '#/components/schemas/Template'
        from_email:
          type: string
          format: email
          nullable: true
        subject:
          type: string
          nullable: true
        html:
          type: string
          nullable: true
        structured_html:
          type: string
          nullable: true
        email_html:
          type: string
          nullable: true
          description: Final rendered HTML sent to subscribers
        webview_html:
          type: string
          nullable: true
        fields:
          type: object
          nullable: true
          additionalProperties: true
          description: Template field values
        mailable_class:
          type: string
          nullable: true
        utm_tags:
          type: boolean
          nullable: true
        add_subscriber_tags:
          type: boolean
          nullable: true
        add_subscriber_link_tags:
          type: boolean
          nullable: true
        sent_to_number_of_subscribers:
          type: integer
        open_count:
          type: integer
        unique_open_count:
          type: integer
        open_rate:
          type: number
          format: float
        click_count:
          type: integer
        unique_click_count:
          type: integer
        click_rate:
          type: number
          format: float
        created_at:
          $ref: '#/components/schemas/Timestamp'
        updated_at:
          $ref: '#/components/schemas/Timestamp'
    AutomationMailRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
        subject:
          type: string
          nullable: true
          description: Defaults to the name when omitted
        template_uuid:
          type: string
          format: uuid
          description: UUID of the template to use
        html:
          type: string
          nullable: true
          description: Raw HTML for the mail. Used when no template_uuid is given, or as the fallback content when a template has no field values. Ignored when both template_uuid and fields are provided.
        fields:
          type: object
          nullable: true
          additionalProperties: true
          description: Values for the chosen template's placeholder fields, keyed by field name. When provided together with template_uuid, the template is rendered with these values to produce the final html. Editor fields accept Markdown when the Markdown editor is configured.
        utm_tags:
          type: boolean
          nullable: true
        add_subscriber_tags:
          type: boolean
          nullable: true
        add_subscriber_link_tags:
          type: boolean
          nullable: true
    TriggerAutomationRequest:
      type: object
      required:
        - subscribers
      properties:
        subscribers:
          type: array
          items:
            type: string
            format: uuid
          description: List of subscriber UUIDs to trigger the automation for
  responses:
    Unauthorized:
      description: Unauthenticated — missing or invalid bearer token
    Forbidden:
      description: Forbidden — insufficient permissions
    UnprocessableEntity:
      description: Validation error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ValidationError'
    NotFound:
      description: Resource not found
    NoContent:
      description: No content — action completed successfully
