openapi: 3.1.0
info:
  title: Loops OpenAPI Spec
  description: This is the OpenAPI Spec for the [Loops API](https://loops.so/docs/api).
  version: 1.21.12
servers:
  - url: https://app.loops.so/api
tags:
  - name: API key
  - name: Audience segments
    description: View audience segments
  - name: Campaigns
    description: Create and manage email campaigns
  - name: Campaign groups
    description: Organize campaigns into groups
  - name: Configuration
    description: View configuration settings
  - name: Contacts
    description: Manage contacts in your audience
  - name: Contact properties
    description: Manage contact properties
  - name: Components
    description: View email components
  - name: Email messages
    description: Manage email message content for campaigns
  - name: Events
    description: Trigger workflows with events
  - name: Event patterns
    description: View workflow event patterns
  - name: Mailing lists
    description: View mailing lists
  - name: Themes
    description: View email themes
  - name: Transactional emails
    description: Create, manage, and send transactional emails
  - name: Transactional groups
    description: Organize transactional emails into groups
  - name: Uploads
    description: Upload image assets
  - name: Workflows
    description: View and mutate workflow graphs
  - name: Workflow nodes
    description: View and mutate workflow nodes
  - name: Webhooks
    description: Events Loops sends to your configured webhook endpoint when certain
      events happen in your account. Configure an endpoint in Settings →
      Webhooks. Each account supports one webhook endpoint. Events are signed
      with `webhook-id`, `webhook-timestamp`, and `webhook-signature` headers
      and delivered at a maximum rate of 10 per second. See
      https://loops.so/docs/webhooks for setup, verification, and payload
      details.
paths:
  /v1/api-key:
    get:
      operationId: testApiKey
      tags:
        - API key
      summary: API key
      description: Test your API key and get team context.
      x-mint:
        href: /api-reference/api-key
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    examples:
                      - true
                  teamName:
                    type: string
                    description: The name of the team the API key belongs to.
                    examples:
                      - Company name
                required:
                  - success
                  - teamName
        "401":
          description: Invalid API key
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    examples:
                      - false
                  message:
                    type: string
                    examples:
                      - Invalid API key
                  error:
                    type: string
                    deprecated: true
                    examples:
                      - Invalid API key
      security:
        - apiKey: []
  /v1/audience-segments/{audienceSegmentId}:
    parameters:
      - name: audienceSegmentId
        in: path
        required: true
        description: The ID of the audience segment.
        schema:
          type: string
          examples:
            - cls6e8g0i2k4m6o8q0s2u4w6
    get:
      operationId: getAudienceSegment
      tags:
        - Audience segments
      summary: Get an audience segment
      description: Retrieve a single audience segment by ID.
      x-mint:
        href: /api-reference/get-audience-segment
        metadata:
          sidebarTitle: Get a segment
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AudienceSegmentResponse"
        "400":
          description: Invalid `audienceSegmentId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AudienceSegmentFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Audience segment not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AudienceSegmentFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/audience-segments:
    get:
      operationId: listAudienceSegments
      tags:
        - Audience segments
      summary: List audience segments
      description: Retrieve a paginated list of audience segments, most recently
        created first.
      x-mint:
        href: /api-reference/list-audience-segments
        metadata:
          sidebarTitle: List segments
      parameters:
        - name: perPage
          in: query
          required: false
          description: How many results to return in each request. Must be between 10 and
            50. Default is 20.
          schema:
            type: string
        - name: cursor
          in: query
          required: false
          description: A cursor to return a specific page of results. Cursors can be found
            from the `pagination.nextCursor` value in each response.
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListAudienceSegmentsResponse"
        "400":
          description: Invalid `perPage` value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AudienceSegmentFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      operationId: createAudienceSegment
      tags:
        - Audience segments
      summary: Create an audience segment
      description: Create a new audience segment.
      x-mint:
        href: /api-reference/create-audience-segment
        metadata:
          sidebarTitle: Create a segment
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateAudienceSegmentRequest"
      responses:
        "200":
          description: Audience segment created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AudienceSegmentResponse"
        "400":
          description: Invalid request body, a name already used by another segment, or a
            filter with too many conditions.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AudienceSegmentFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: The filter references a campaign, workflow or workflow email that
            does not exist.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AudienceSegmentFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/campaigns:
    get:
      operationId: listCampaigns
      tags:
        - Campaigns
      summary: List campaigns
      description: Retrieve a paginated list of campaigns.
      x-mint:
        href: /api-reference/list-campaigns
      parameters:
        - name: perPage
          in: query
          required: false
          description: How many results to return in each request. Must be between 10 and
            50. Default is 20.
          schema:
            type: string
        - name: cursor
          in: query
          required: false
          description: A cursor to return a specific page of results. Cursors can be found
            from the `pagination.nextCursor` value in each response.
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListCampaignsResponse"
        "400":
          description: Invalid `perPage` value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      operationId: createCampaign
      tags:
        - Campaigns
      summary: Create a campaign
      description: Create a new draft campaign. An empty email message is created
        automatically and its `emailMessageId` is returned. Use the
        `/email-messages/{emailMessageId}` endpoint to set subject, sender,
        preview text, and LMX content. The audience (mailing list, segment, or
        filter), group, and scheduling can be set on create or later via update.
      x-mint:
        href: /api-reference/create-campaign
        metadata:
          description: Create a draft marketing campaign and its associated email message.
        content: >-
          This endpoint creates a draft campaign and an empty email message in
          one step. Use the returned `emailMessageId` with [Update an email
          message](/api-reference/update-email-message) to set subject, sender,
          preview text, and LMX content.


          The audience (mailing list, segment, or filter), group, and scheduling
          can be set on create or later via [Update a
          campaign](/api-reference/update-campaign).


          <Tip>To send a test preview of a campaign, use the [Preview email
          message](/api-reference/preview-email-message) endpoint.</Tip>
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateCampaignRequest"
      responses:
        "201":
          description: Campaign created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateCampaignResponse"
        "400":
          description: Invalid request body, campaign group not found, or no sending
            domain configured.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Referenced mailing list or audience segment not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/campaigns/{campaignId}:
    parameters:
      - name: campaignId
        in: path
        required: true
        description: The ID of the campaign.
        schema:
          type: string
          examples:
            - clc4m6n8p0q2r4s6t8u0v2x4
    get:
      operationId: getCampaign
      tags:
        - Campaigns
      summary: Get a campaign
      description: Retrieve a single campaign by ID.
      x-mint:
        href: /api-reference/get-campaign
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignResponse"
        "400":
          description: Invalid `campaignId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Campaign not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      operationId: updateCampaign
      tags:
        - Campaigns
      summary: Update a campaign
      description: Update a draft campaign's name, group, audience (mailing list,
        segment, or filter), or scheduling. At least one field must be provided.
        Once a campaign has been sent, only its `name` and `campaignGroupId` can
        be updated.
      x-mint:
        href: /api-reference/update-campaign
        metadata:
          description: Update a draft campaign's name, group, audience (mailing list,
            segment, or filter), or scheduling.
        content: <Info>At least one field must be provided. Draft campaigns support
          every field below. Once a campaign has been sent, only `name` and
          `campaignGroupId` can be updated.</Info>
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateCampaignRequest"
      responses:
        "200":
          description: Campaign updated.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignResponse"
        "400":
          description: Invalid request body or campaign group not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Campaign, mailing list, or audience segment not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: Campaign has been sent and the request updates a field other than
            `name` or `campaignGroupId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
      security:
        - apiKey: []
  /v1/campaign-groups:
    get:
      operationId: listCampaignGroups
      tags:
        - Campaign groups
      summary: List campaign groups
      description: Retrieve a paginated list of campaign groups, most recently created
        first.
      x-mint:
        href: /api-reference/list-campaign-groups
        metadata:
          sidebarTitle: List groups
      parameters:
        - name: perPage
          in: query
          required: false
          description: How many results to return in each request. Must be between 10 and
            50. Default is 20.
          schema:
            type: string
        - name: cursor
          in: query
          required: false
          description: A cursor to return a specific page of results. Cursors can be found
            from the `pagination.nextCursor` value in each response.
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListGroupsResponse"
        "400":
          description: Invalid `perPage` value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      operationId: createCampaignGroup
      tags:
        - Campaign groups
      summary: Create a campaign group
      description: Create a new campaign group.
      x-mint:
        href: /api-reference/create-campaign-group
        metadata:
          sidebarTitle: Create a group
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateGroupRequest"
      responses:
        "200":
          description: Campaign group created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupResponse"
        "400":
          description: Invalid request body or reserved group name.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/campaign-groups/{campaignGroupId}:
    parameters:
      - name: campaignGroupId
        in: path
        required: true
        description: The ID of the campaign group.
        schema:
          type: string
          examples:
            - clg7n5p3q1r9s7t5u3v1w9y7
    get:
      operationId: getCampaignGroup
      tags:
        - Campaign groups
      summary: Get a campaign group
      description: Retrieve a single campaign group by ID.
      x-mint:
        href: /api-reference/get-campaign-group
        metadata:
          sidebarTitle: Get a group
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupResponse"
        "400":
          description: Invalid `campaignGroupId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Campaign group not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      operationId: updateCampaignGroup
      tags:
        - Campaign groups
      summary: Update a campaign group
      description: Update a campaign group's name or description. At least one field
        must be provided. The reserved "Unsorted" group cannot be edited.
      x-mint:
        href: /api-reference/update-campaign-group
        content: <Info>At least one field must be provided. The reserved "Unsorted"
          group cannot be edited.</Info>
        metadata:
          description: Update a campaign group's name or description.
          sidebarTitle: Update a group
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateGroupRequest"
      responses:
        "200":
          description: Campaign group updated.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupResponse"
        "400":
          description: Invalid request body, reserved group name, or the Unsorted group
            cannot be edited.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Campaign group not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/dedicated-sending-ips:
    get:
      operationId: listDedicatedSendingIps
      tags:
        - Configuration
      summary: List dedicated sending IP addresses
      description: >-
        Retrieve a list of Loops' dedicated sending IP addresses.


        This endpoint is provided for the rare instances where you may need to
        whitelist our sending IPs. Please note that this list is subject to
        change and will not include shared IPs used for sending mail.


        Unless you are sure you need this and are comfortable watching for
        changes, we strongly recommend you _do not_ whitelist these IPs.
      x-mint:
        href: /api-reference/dedicated-sending-ips
        metadata:
          description: Retrieve a list of Loops' dedicated sending IP addresses.
          sidebarTitle: List sending IPs
        content: <Warning>This endpoint is provided for the rare instances where you may
          need to whitelist our sending IPs. Please note that this list is
          subject to change and will not include shared IPs used for sending
          mail. Unless you are sure you need this and are comfortable watching
          for changes, we strongly recommend you _do not_ whitelist these
          IPs.</Warning>
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                type: array
                description: Returns an array of IP address strings.
                items:
                  type: string
                  description: IP address
                  examples:
                    - 52.21.45.123
                example:
                  - 52.21.45.123
                  - 52.21.45.124
                  - 52.21.45.125
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/contacts/create:
    post:
      operationId: createContact
      tags:
        - Contacts
      summary: Create a contact
      description: Add a contact to your audience.
      x-mint:
        href: /api-reference/create-contact
        content: <Tip>If you want to "update or create" contacts, consider using the
          [Update a contact](https://loops.so/docs/api-reference/update-contact)
          endpoint instead.</Tip>
      requestBody:
        description: You can add custom contact properties as keys in this request (of
          type `string`, `number`, `boolean` or `date`. [See available date
          formats](https://loops.so/docs/contacts/properties#dates)). Make sure
          to create the properties in Loops before using them in API calls.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ContactRequest"
        required: true
      responses:
        "200":
          description: Successful create.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactSuccessResponse"
        "400":
          description: Bad request (e.g. invalid email address).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: Email or `userId` already exists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
      security:
        - apiKey: []
  /v1/contacts/update:
    put:
      operationId: updateContact
      tags:
        - Contacts
      summary: Update a contact
      description: >-
        Update a contact by `email` or `userId`. You must provide one of these
        parameters.


        If you want to update a contact's email address, the contact will first
        need a `userId` value. You can then make a request containing the
        `userId` field along with an updated email address.


        This endpoint will create a contact if a matching contact does not
        already exist in your audience.


        Provide either `email` or `userId` to identify the contact you want to
        update. If both are provided, the system will look for a contact with
        either a matching `email` or `userId` value. If a contact is found for
        one of the values (e.g. `email`), the other value (e.g. `userId`) will
        be updated. If a contact is not found, a new contact will be created
        using both `email` and `userId` values.
      x-mint:
        href: /api-reference/update-contact
        content: >-
          Update a contact by `email` or `userId`. You must provide one of these
          parameters.


          If you want to update a contact's email address, the contact will
          first need a `userId` value. You can then make a request containing
          the `userId` field along with an updated email address.


          This endpoint will create a contact if a matching contact does not
          already exist in your audience.


          <Note>Provide either `email` or `userId` to identify the contact you
          want to update. If both are provided, the system will look for a
          contact with either a matching `email` or `userId` value. If a contact
          is found for one of the values (e.g. `email`), the other value (e.g.
          `userId`) will be updated. If a contact is not found, a new contact
          will be created using both `email` and `userId` values.</Note>
        metadata:
          sidebarTitle: Update a contact
          description: Update or create a contact.
      requestBody:
        description: You can add custom contact properties as keys in this request (of
          type `string`, `number`, `boolean` or `date`. [See available date
          formats](https://loops.so/docs/contacts/properties#dates)). Make sure
          to create the properties in Loops before using them in API calls.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ContactUpdateRequest"
        required: true
      responses:
        "200":
          description: Successful update.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactSuccessResponse"
        "400":
          description: Bad request (e.g. `email` or `userId` are missing).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/contacts/find:
    get:
      operationId: findContact
      tags:
        - Contacts
      summary: Find a contact
      description: Search for a contact by `email` or `userId`. Only one parameter is
        allowed.
      x-mint:
        href: /api-reference/find-contact
        content: Search for a contact by `email` or `userId`. Only one parameter is
          allowed.
        metadata:
          description: Find a contact by email address or user ID.
      parameters:
        - name: email
          in: query
          required: false
          description: Email address (URI-encoded)
          schema:
            type: string
        - name: userId
          in: query
          required: false
          schema:
            type: string
      responses:
        "200":
          description: List of contacts (or an empty array if no contact was found).
            Contact objects will include any custom properties.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Contact"
        "400":
          description: Bad request (e.g. invalid email address).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/contacts/delete:
    post:
      operationId: deleteContact
      tags:
        - Contacts
      summary: Delete a contact
      description: Delete a contact by `email` or `userId`.
      x-mint:
        href: /api-reference/delete-contact
        content: Delete a contact by `email` or `userId`.
        metadata:
          sidebarTitle: Delete a contact
          description: Delete a contact by email address or user ID.
      requestBody:
        description: Include only one of `email` or `userId`.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ContactDeleteRequest"
        required: true
      responses:
        "200":
          description: Successful delete.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactDeleteResponse"
        "400":
          description: Bad request (e.g. `email` and `userId` are both provided).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "404":
          description: Contact not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/contacts/suppression:
    get:
      operationId: getContactSuppression
      tags:
        - Contacts
      summary: Get suppression status for a contact
      description: Retrieve suppression status and removal quota for a contact by
        `email` or `userId`. Include only one query parameter.
      x-mint:
        href: /api-reference/check-contact-suppression
        metadata:
          title: Check contact suppression status
          sidebarTitle: Check suppression
          description: Check if a contact is suppressed by email address or user ID.
      parameters:
        - name: email
          in: query
          required: false
          description: Email address (URI-encoded)
          schema:
            type: string
        - name: userId
          in: query
          required: false
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactSuppressionStatusResponse"
        "400":
          description: Bad request (e.g. invalid email address).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "404":
          description: Contact not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    delete:
      operationId: removeContactSuppression
      tags:
        - Contacts
      summary: Remove a contact from suppression list
      description: Remove a suppressed contact from the suppression list by `email` or
        `userId`. Include only one query parameter.
      x-mint:
        href: /api-reference/remove-contact-suppression
        metadata:
          title: Remove contact from suppression
          sidebarTitle: Remove suppression
          description: Remove suppression for a contact by email address or user ID.
      parameters:
        - name: email
          in: query
          required: false
          description: Email address (URI-encoded)
          schema:
            type: string
        - name: userId
          in: query
          required: false
          schema:
            type: string
      responses:
        "200":
          description: Successful removal.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactSuppressionRemoveResponse"
        "400":
          description: Bad request (e.g. contact is not suppressed).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "404":
          description: Contact not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/contacts/properties:
    post:
      operationId: createContactProperty
      tags:
        - Contact properties
      summary: Create a contact property
      description: Create a custom contact property.
      x-mint:
        href: /api-reference/create-contact-property
        metadata:
          sidebarTitle: Create property
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ContactPropertyCreateRequest"
        required: true
      responses:
        "200":
          description: Successful create.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactPropertySuccessResponse"
        "400":
          description: Bad request (e.g. invalid type).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactPropertyFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    get:
      operationId: listContactProperties
      tags:
        - Contact properties
      summary: List contact properties
      description: Retrieve a list of your account's contact properties.<br>Use the
        `list` parameter to query "all" or "custom" properties.
      x-mint:
        href: /api-reference/list-contact-properties
        metadata:
          sidebarTitle: List properties
          description: Retrieve a list of your account's contact properties.
      parameters:
        - name: list
          in: query
          required: false
          description: "`all` (default) or `custom` (only custom contact properties)"
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ContactProperty"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/components/{componentId}:
    parameters:
      - name: componentId
        in: path
        required: true
        description: The ID of the component.
        schema:
          type: string
          examples:
            - clp2o4i6u8y0t5r3e1w7q9s1
    get:
      operationId: getComponent
      tags:
        - Components
      summary: Get a component
      description: Retrieve a single component by ID.
      x-mint:
        href: /api-reference/get-component
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentResponse"
        "400":
          description: Invalid `componentId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Component not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      operationId: updateComponent
      tags:
        - Components
      summary: Update a component
      description: Update a component's name and/or body. When the `lmx` body changes,
        the update cascades to every email using this component, and
        `affectedEmailCount` reports how many were affected. A change that would
        introduce a dynamic variable an email using the component cannot use is
        rejected.
      x-mint:
        href: /api-reference/update-component
        content: When the `lmx` body changes, the update cascades to every email using
          this component, and `affectedEmailCount` reports how many were
          affected. A change that would introduce a dynamic variable an email
          using the component cannot use is rejected.
        metadata:
          description: Update a component's name and/or LMX body. Body changes cascade to
            every email using the component.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateComponentBody"
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UpdateComponentResponse"
        "400":
          description: Invalid `componentId` or request body.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Component not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "413":
          description: LMX body exceeds the size limit.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentFailureResponse"
        "422":
          description: Invalid LMX, or a body change that would break emails using the
            component.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentValidationFailureResponse"
      security:
        - apiKey: []
  /v1/components:
    get:
      operationId: listComponents
      tags:
        - Components
      summary: List components
      description: Retrieve a paginated list of email components.
      x-mint:
        href: /api-reference/list-components
      parameters:
        - name: perPage
          in: query
          required: false
          description: How many results to return in each request. Must be between 10 and
            50. Default is 20.
          schema:
            type: string
        - name: cursor
          in: query
          required: false
          description: A cursor to return a specific page of results. Cursors can be found
            from the `pagination.nextCursor` value in each response.
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListComponentsResponse"
        "400":
          description: Invalid `perPage` value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      operationId: createComponent
      tags:
        - Components
      summary: Create a component
      description: Create a new email component from an LMX body.
      x-mint:
        href: /api-reference/create-component
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateComponentBody"
      responses:
        "201":
          description: Component created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentResponse"
        "400":
          description: Invalid request body.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
        "413":
          description: LMX body exceeds the size limit.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentFailureResponse"
        "422":
          description: Invalid LMX.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentFailureResponse"
      security:
        - apiKey: []
  /v1/email-messages/{emailMessageId}:
    parameters:
      - name: emailMessageId
        in: path
        required: true
        description: The ID of the email message.
        schema:
          type: string
          examples:
            - cle5f7g9h1i3j5k7l9m1n3p5
    get:
      operationId: getEmailMessage
      tags:
        - Email messages
      summary: Get an email message
      description: Retrieve an email message, including its compiled LMX content.
      x-mint:
        href: /api-reference/get-email-message
        metadata:
          sidebarTitle: Get an email
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageResponse"
        "400":
          description: Invalid `emailMessageId` or no sending domain configured.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Email message not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: Email message uses MJML format or content cannot be parsed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
      security:
        - apiKey: []
    post:
      operationId: updateEmailMessage
      tags:
        - Email messages
      summary: Update an email message
      description: Update fields on an email message (subject, preview text, sender,
        LMX content). The campaign must be in draft status. Supply
        `expectedRevisionId` matching the current `contentRevisionId` — the
        server rejects mismatched revisions with 409.
      x-mint:
        href: /api-reference/update-email-message
        metadata:
          description: Update an email message's subject, preview text, sender, or LMX
            content.
          sidebarTitle: Update an email
        content: >-
          Supply `expectedRevisionId` matching the current `contentRevisionId`.


          <Info>The campaign or transactional email that owns this email message
          must be in `Draft` status.</Info>
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateEmailMessageRequest"
      responses:
        "200":
          description: Email message updated.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageResponse"
        "400":
          description: Invalid request body.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Email message not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: Campaign is not in draft status, `contentRevisionId` is stale,
            content cannot be parsed, or email message uses MJML format.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "413":
          description: LMX payload exceeds the 100KB limit.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "422":
          description: LMX failed to compile.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
      security:
        - apiKey: []
  /v1/email-messages/{emailMessageId}/preview:
    parameters:
      - name: emailMessageId
        in: path
        required: true
        description: The ID of the email message.
        schema:
          type: string
          examples:
            - cle5f7g9h1i3j5k7l9m1n3p5
    post:
      operationId: previewEmailMessage
      tags:
        - Email messages
      summary: Send a preview of an email message
      description: Send a test preview of an email message to one or more addresses.
        The accepted variable fields depend on the parent's type - campaign
        previews accept `contactProperties`, workflow previews accept
        `contactProperties` and `eventProperties`, and transactional previews
        accept `dataVariables`. Supplying a field the parent cannot reference is
        rejected with 400.
      x-mint:
        href: /api-reference/preview-email-message
        content: >-
          Send a test email message to one or more addresses. Accepted variable
          fields depend on the parent's type:


          - **Campaign** accepts `contactProperties`.

          - **Workflow** accepts `contactProperties` and `eventProperties`.

          - **Transactional** accepts `dataVariables`.


          Supplying a field the parent cannot reference results in a `400 Bad
          Request` error.


          Each team can send up to 100 preview emails per day.
        metadata:
          description: Send a test preview of an email message to one or more addresses.
          sidebarTitle: Preview email
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/EmailMessagePreviewRequest"
      responses:
        "200":
          description: Preview scheduled.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessagePreviewResponse"
        "400":
          description: Invalid request body, or a variable field the parent cannot
            reference.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Email message not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "429":
          description: The daily preview limit was reached.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
      security:
        - apiKey: []
  /v1/email-messages/{emailMessageId}/guardian:
    parameters:
      - name: emailMessageId
        in: path
        required: true
        description: The ID of the email message.
        schema:
          type: string
          examples:
            - cle5f7g9h1i3j5k7l9m1n3p5
    get:
      operationId: getEmailMessageGuardian
      tags:
        - Email messages
      summary: Run Guardian checks on an email message
      description: Validate an email message's content against Guardian rules and
        return any errors and warnings. Errors must be resolved before the email
        can be published, warnings are advisory.
      x-mint:
        href: /api-reference/run-guardian-checks
        content: >-
          Run the same [Guardian](/creating-emails/guardian) checks that run in
          the Loops editor on a saved email message. Use this to validate
          campaign, workflow, and transactional email content before publishing
          or sending.


          Checks depend on the email message's parent type:


          - **Campaign** validates contact properties and rendered links and
          buttons.

          - **Workflow** validates contact properties, event properties from the
          workflow's event trigger, and rendered links and buttons.

          - **Transactional** validates data variables and rendered links and
          buttons.

          - **System transactional** validates required data variables and
          rendered links and buttons.


          <Info>This will not work on MJML email messages, as they are not
          supported in the API.</Info>
        metadata:
          description: Run Guardian content validation on an email message and return
            errors and warnings before you publish or send.
          sidebarTitle: Guardian checks
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageGuardianResponse"
        "400":
          description: Invalid `emailMessageId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Email message not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: Email message uses MJML format.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
      security:
        - apiKey: []
  /v1/events/send:
    post:
      operationId: sendEvent
      tags:
        - Events
      summary: Send an event
      description: Send events to trigger workflows.
      x-mint:
        href: /api-reference/send-event
        content: <Note>Provide either an `email` or `userId` value or both to identify
          the contact. If both are provided, the system will look for a contact
          with either a matching `email` or `userId` value. If a contact is
          found for one of the values (e.g. `email`), the other value (e.g.
          `userId`) will be updated. If a contact is not found, a new contact
          will be created using both `email` and `userId` values.</Note>
      requestBody:
        description: Provide either `email` or `userId` to identify the contact ([read
          more](https://loops.so/docs/api-reference/send-event#body)).<br>Event
          properties will be available in emails sent by this event. Values of
          properties can be of type `string`, `number`, `boolean` or `date`
          ([see allowed date
          formats](https://loops.so/docs/events/properties#important-information-about-event-properties)).<br>Make
          sure to create the properties in Loops before using them in API
          calls.<br>You can add contact properties as keys in this request (of
          type `string`, `number`, `boolean` or `date` ([see available date
          formats](https://loops.so/docs/contacts/properties#dates))).
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/EventRequest"
        required: true
      parameters:
        - in: header
          name: Idempotency-Key
          description: >-
            Include a unique ID for this request (maximum 100 characters) to
            avoid duplicate emails.


            The value should be a string of up to 100 characters and should be
            unique for each request. We recommend using V4 UUIDs or some other
            method with enough guaranteed entropy to avoid collisions during a
            24 hour window.


            This endpoint will return a `409 Conflict` response if the
            idempotency key has been used in the previous 24 hours.
          schema:
            type: string
            maxLength: 100
      responses:
        "200":
          description: Successful send.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EventSuccessResponse"
        "400":
          description: Bad request (e.g. `eventName` is missing).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EventFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: Idempotency key has been used.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IdempotencyKeyFailureResponse"
      security:
        - apiKey: []
  /v1/event-patterns:
    get:
      tags:
        - Event patterns
      summary: List event patterns
      operationId: listEventPatterns
      description: Retrieve a paginated list of event patterns available to workflow
        event trigger nodes.
      x-mint:
        href: /api-reference/list-event-patterns
      parameters:
        - name: perPage
          in: query
          required: false
          description: How many results to return in each request. Must be between 10 and
            50. Default is 20.
          schema:
            type: string
        - name: cursor
          in: query
          required: false
          description: A cursor to return a specific page of results. Cursors can be found
            from the `pagination.nextCursor` value in each response.
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListEventPatternsResponse"
        "400":
          description: Invalid `perPage` or `cursor` value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EventPatternFailureResponse"
        "401":
          description: Invalid API key.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/event-patterns/by-name/{eventName}:
    parameters:
      - name: eventName
        in: path
        required: true
        description: The exact event name. Event names are case-sensitive and should be
          URL-encoded if they contain special characters.
        schema:
          type: string
    get:
      tags:
        - Event patterns
      summary: Get an event pattern by name
      operationId: getEventPatternByName
      description: Retrieve event pattern details by event name for a workflow event
        trigger. Event names are case-sensitive, so `PaymentReceived` and
        `paymentReceived` are different events.
      x-mint:
        href: /api-reference/get-event-pattern-by-name
        metadata:
          sidebarTitle: Get by name
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EventPattern"
        "400":
          description: Invalid `eventName`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EventPatternFailureResponse"
        "401":
          description: Invalid API key.
        "404":
          description: Event pattern not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EventPatternFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/event-patterns/{eventPatternId}:
    parameters:
      - name: eventPatternId
        in: path
        required: true
        description: The ID of the event pattern.
        schema:
          type: string
    get:
      tags:
        - Event patterns
      summary: Get an event pattern by ID
      operationId: getEventPattern
      description: Retrieve event pattern details for a workflow event trigger.
      x-mint:
        href: /api-reference/get-event-pattern
        metadata:
          sidebarTitle: Get by ID
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EventPattern"
        "400":
          description: Invalid `eventPatternId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EventPatternFailureResponse"
        "401":
          description: Invalid API key.
        "404":
          description: Event pattern not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EventPatternFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/lists:
    get:
      operationId: listMailingLists
      tags:
        - Mailing lists
      summary: List mailing lists
      description: Retrieve a list of your account's mailing lists.
      x-mint:
        href: /api-reference/list-mailing-lists
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MailingList"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/themes/{themeId}:
    parameters:
      - name: themeId
        in: path
        required: true
        description: The ID of the theme.
        schema:
          type: string
          examples:
            - clt3u5v7w9x1y3z5a7b9c1d3
    get:
      operationId: getTheme
      tags:
        - Themes
      summary: Get a theme
      description: Retrieve a single theme by ID.
      x-mint:
        href: /api-reference/get-theme
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ThemeResponse"
        "400":
          description: Invalid `themeId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ThemeFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Theme not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ThemeFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      operationId: updateTheme
      tags:
        - Themes
      summary: Update a theme
      description: "Update a theme's name and/or styles. When `styles` change, the
        update cascades to every email using this theme, and
        `affectedEmailCount` in the response reports how many emails were
        affected. Manual style edits made on individual emails are preserved:
        the cascade only changes properties an email has not overridden. A
        per-email override is removed only when it becomes identical to the
        theme's new value, after which that email follows the theme for that
        property."
      x-mint:
        href: /api-reference/update-theme
        content: >-
          When `styles` change, the update cascades to every email using this
          theme, and `affectedEmailCount` in the response reports how many
          emails were affected.


          Manual style edits made on individual emails are preserved: the
          cascade only changes properties an email has not overridden. A
          per-email override is removed only when it becomes identical to the
          theme's new value, after which that email follows the theme for that
          property.
        metadata:
          description: Update a theme's name and/or styles. Style changes cascade to every
            email using the theme.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateThemeBody"
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UpdateThemeResponse"
        "400":
          description: Invalid `themeId` or request body.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ThemeFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Theme not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ThemeFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/themes:
    get:
      operationId: listThemes
      tags:
        - Themes
      summary: List themes
      description: Retrieve a paginated list of email themes, most recently created first.
      x-mint:
        href: /api-reference/list-themes
      parameters:
        - name: perPage
          in: query
          required: false
          description: How many results to return in each request. Must be between 10 and
            50. Default is 20.
          schema:
            type: string
        - name: cursor
          in: query
          required: false
          description: A cursor to return a specific page of results. Cursors can be found
            from the `pagination.nextCursor` value in each response.
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListThemesResponse"
        "400":
          description: Invalid `perPage` value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ThemeFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      operationId: createTheme
      tags:
        - Themes
      summary: Create a theme
      description: Create a new email theme for use across Loops emails.
      x-mint:
        href: /api-reference/create-theme
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateThemeBody"
      responses:
        "201":
          description: Theme created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ThemeResponse"
        "400":
          description: Invalid request body.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ThemeFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/transactional:
    post:
      operationId: sendTransactionalEmail
      tags:
        - Transactional emails
      summary: Send a transactional email
      description: >-
        Send a transactional email to a contact.<br>Please [email
        us](mailto:help@loops.so) to enable attachments on your account before
        using them with the API.


        To set dynamic Subject, From, Reply to, CC, BCC email header fields, add
        data variables to those fields in the editor, then include data for each
        variable in the API request. Read our transactional email guide for more
        details.
      x-mint:
        metadata:
          description: Send a transactional email.
          sidebarTitle: Send transactional
        href: /api-reference/send-transactional-email
        content: >-
          Send a transactional email, including optional data variables, to a
          single recipient.


          To set dynamic Subject, From, Reply to, CC, BCC email header fields,
          add data variables to those fields in the editor, then include data
          for each variable in the API request. Read our [transactional email
          guide](/transactional) for more details.


          To send a test preview of a transactional email, use the [Preview
          email message](/api-reference/preview-email-message) endpoint.


          <Note>Please [email us](mailto:help@loops.so) to enable attachments on
          your account before using them with the API.</Note>
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TransactionalRequest"
        required: true
      parameters:
        - in: header
          name: Idempotency-Key
          description: >-
            Include a unique ID for this request (maximum 100 characters) to
            avoid duplicate emails.


            The value should be a string of up to 100 characters and should be
            unique for each request. We recommend using V4 UUIDs or some other
            method with enough guaranteed entropy to avoid collisions during a
            24 hour window.


            This endpoint will return a `409 Conflict` response if the
            idempotency key has been used in the previous 24 hours.
          schema:
            type: string
            maxLength: 100
      responses:
        "200":
          description: Successful send.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalSuccessResponse"
        "400":
          description: Bad request (e.g. transactional email is not published).
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/TransactionalSendFailureResponse"
                  - $ref: "#/components/schemas/TransactionalFailure2Response"
                  - $ref: "#/components/schemas/TransactionalFailure3Response"
                  - $ref: "#/components/schemas/TransactionalFailure4Response"
                  - $ref: "#/components/schemas/TransactionalFailure5Response"
        "404":
          description: Transactional email not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailure3Response"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: Idempotency key has been used.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IdempotencyKeyFailureResponse"
      security:
        - apiKey: []
    get:
      operationId: listPublishedTransactionalEmails
      deprecated: true
      tags:
        - Transactional emails
      summary: List transactional emails (legacy)
      description: Get a list of published transactional emails.
      x-mint:
        href: /api-reference/list-transactional-emails-v1
        metadata:
          sidebarTitle: List transactionals (legacy)
        content: <Warning>This endpoint is deprecated. Use [List transactional
          emails](/api-reference/list-transactional-emails) instead.</Warning>
      parameters:
        - name: perPage
          in: query
          required: false
          description: How many results to return in each request. Must be between 10 and
            50. Default is 20.
          schema:
            type: string
        - name: cursor
          in: query
          required: false
          description: A cursor, to return a specific page of results. Cursors can be
            found from the `pagination.nextCursor` value in each response.
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListTransactionalsResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/transactional-emails:
    get:
      operationId: listTransactionalEmails
      tags:
        - Transactional emails
      summary: List transactional emails
      description: Retrieve a paginated list of transactional emails, most recently
        created first.
      x-mint:
        href: /api-reference/list-transactional-emails
        metadata:
          sidebarTitle: List transactionals
      parameters:
        - name: perPage
          in: query
          required: false
          description: How many results to return in each request. Must be between 10 and
            50. Default is 20.
          schema:
            type: string
        - name: cursor
          in: query
          required: false
          description: A cursor to return a specific page of results. Cursors can be found
            from the `pagination.nextCursor` value in each response.
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListTransactionalsResourceResponse"
        "400":
          description: Invalid `perPage` value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      operationId: createTransactionalEmail
      tags:
        - Transactional emails
      summary: Create a transactional email
      description: Create a new transactional email. An empty draft email message is
        created automatically and its `draftEmailMessageId` is returned. Use the
        `POST /v1/email-messages/{emailMessageId}` endpoint along with the
        returned `draftEmailMessageContentRevisionId` to set subject, sender,
        preview text, and LMX content, then call `POST
        /v1/transactional-emails/{transactionalId}/publish` to publish the
        draft.
      x-mint:
        href: /api-reference/create-transactional-email
        content: >-
          This endpoint creates a transactional email and an empty draft email
          message in one step.


          Use the returned `draftEmailMessageId` and
          `draftEmailMessageContentRevisionId` when calling the [Update email
          message](/api-reference/update-email-message) endpoint to set subject,
          sender, preview text, and LMX content.


          Call [Publish transactional email
          draft](/api-reference/publish-transactional-email) to publish.
        metadata:
          sidebarTitle: Create transactional
          description: Create a new transactional email and its draft email message, ready
            for editing, previewing, and publishing through the Loops API.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateTransactionalRequest"
      responses:
        "201":
          description: Transactional email created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalDraftResponse"
        "400":
          description: Invalid request body or no sending domain configured.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/transactional-emails/{transactionalId}:
    parameters:
      - name: transactionalId
        in: path
        required: true
        description: The ID of the transactional email.
        schema:
          type: string
          examples:
            - cll42l54f20i1la0lfooe3z12
    get:
      operationId: getTransactionalEmail
      tags:
        - Transactional emails
      summary: Get a transactional email
      description: Retrieve a single transactional email by ID.
      x-mint:
        href: /api-reference/get-transactional-email
        metadata:
          sidebarTitle: Get transactional
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalResource"
        "400":
          description: Invalid `transactionalId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Transactional email not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      operationId: updateTransactionalEmail
      tags:
        - Transactional emails
      summary: Update a transactional email
      description: Update a transactional email by ID.
      x-mint:
        href: /api-reference/update-transactional-email
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateTransactionalRequest"
      responses:
        "200":
          description: Transactional email updated.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalResource"
        "400":
          description: Invalid request body or `transactionalId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Transactional email not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/transactional-emails/{transactionalId}/draft:
    parameters:
      - name: transactionalId
        in: path
        required: true
        description: The ID of the transactional email.
        schema:
          type: string
          examples:
            - cll42l54f20i1la0lfooe3z12
    post:
      operationId: ensureTransactionalDraft
      tags:
        - Transactional emails
      summary: Ensure a draft email message
      description: Ensure the transactional email has a draft email message. If a
        draft already exists it is returned unchanged; otherwise a new empty
        draft is created (seeded from the most recent published version when
        present). Use `POST /v1/email-messages/{emailMessageId}` to edit the
        draft's content.
      x-mint:
        href: /api-reference/ensure-transactional-draft
        content: >-
          If a draft email message already exists, it is returned unchanged.
          Otherwise a new empty draft is created (seeded from the most recent
          published version when present).


          Use the returned `draftEmailMessageId` and
          `draftEmailMessageContentRevisionId` when calling [Update an email
          message](/api-reference/update-email-message) to edit the draft's
          content.
        metadata:
          title: Ensure a transactional email has a draft
          sidebarTitle: Ensure draft
          description: Ensure a transactional email has a draft email message ready for
            editing, creating one from the published version if no draft
            currently exists.
      responses:
        "200":
          description: Draft ready.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalDraftResponse"
        "400":
          description: Invalid `transactionalId` or no sending domain configured.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Transactional email not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/transactional-emails/{transactionalId}/publish:
    parameters:
      - name: transactionalId
        in: path
        required: true
        description: The ID of the transactional email.
        schema:
          type: string
          examples:
            - cll42l54f20i1la0lfooe3z12
    post:
      operationId: publishTransactionalEmail
      tags:
        - Transactional emails
      summary: Publish a transactional email draft
      description: Publish the transactional email's current draft email message. The
        draft becomes the published version and the draft is cleared.
      x-mint:
        href: /api-reference/publish-transactional-email
        content: >-
          The transactional email's current draft email message is published.
          The draft becomes the published version and the draft is cleared.


          After publishing, use the returned `id` as `transactionalId` with
          [Send a transactional email](/api-reference/send-transactional-email)
          to send the email.
        metadata:
          title: Publish a transactional email
          sidebarTitle: Publish transactional
      responses:
        "200":
          description: Transactional email published.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalResource"
        "400":
          description: Invalid `transactionalId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Transactional email not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: No draft to publish.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "422":
          description: Draft failed validation, sending domain is not verified, or content
            was flagged as unsafe.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
      security:
        - apiKey: []
  /v1/transactional-groups:
    get:
      operationId: listTransactionalGroups
      tags:
        - Transactional groups
      summary: List transactional groups
      description: Retrieve a paginated list of transactional groups, most recently
        created first.
      x-mint:
        href: /api-reference/list-transactional-groups
        metadata:
          sidebarTitle: List groups
      parameters:
        - name: perPage
          in: query
          required: false
          description: How many results to return in each request. Must be between 10 and
            50. Default is 20.
          schema:
            type: string
        - name: cursor
          in: query
          required: false
          description: A cursor to return a specific page of results. Cursors can be found
            from the `pagination.nextCursor` value in each response.
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListGroupsResponse"
        "400":
          description: Invalid `perPage` value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      operationId: createTransactionalGroup
      tags:
        - Transactional groups
      summary: Create a transactional group
      description: Create a new transactional group.
      x-mint:
        href: /api-reference/create-transactional-group
        metadata:
          sidebarTitle: Create a group
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateGroupRequest"
      responses:
        "200":
          description: Transactional group created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupResponse"
        "400":
          description: Invalid request body or reserved group name.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/transactional-groups/{transactionalGroupId}:
    parameters:
      - name: transactionalGroupId
        in: path
        required: true
        description: The ID of the transactional group.
        schema:
          type: string
          examples:
            - clg7n5p3q1r9s7t5u3v1w9y7
    get:
      operationId: getTransactionalGroup
      tags:
        - Transactional groups
      summary: Get a transactional group
      description: Retrieve a single transactional group by ID.
      x-mint:
        href: /api-reference/get-transactional-group
        metadata:
          sidebarTitle: Get a group
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupResponse"
        "400":
          description: Invalid `transactionalGroupId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Transactional group not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      operationId: updateTransactionalGroup
      tags:
        - Transactional groups
      summary: Update a transactional group
      description: Update a transactional group's name or description. At least one
        field must be provided. The reserved "Unsorted" group cannot be edited.
      x-mint:
        href: /api-reference/update-transactional-group
        content: <Info>At least one field must be provided. The reserved "Unsorted"
          group cannot be edited.</Info>
        metadata:
          sidebarTitle: Update a group
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateGroupRequest"
      responses:
        "200":
          description: Transactional group updated.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupResponse"
        "400":
          description: Invalid request body, reserved group name, or the Unsorted group
            cannot be edited.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Transactional group not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GroupFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/uploads:
    post:
      operationId: createUpload
      tags:
        - Uploads
      summary: Create an upload
      description: Request a pre-signed URL to upload an image asset. Upload the file
        with an HTTP `PUT` to the returned `presignedUrl` (sending the same
        `Content-Type` and `Content-Length`), then call
        `/uploads/{emailAssetId}/complete` to finalize the asset.
      x-mint:
        href: /api-reference/create-upload
        content: Request a pre-signed URL to upload an image asset. Upload the file with
          an HTTP `PUT` to the returned `presignedUrl` (sending the same
          `Content-Type` and `Content-Length`), then call [Complete an
          upload](/api-reference/complete-upload) to finalize the asset.
        metadata:
          description: Request a pre-signed URL to upload an image asset.
          sidebarTitle: Create an upload
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateUploadRequest"
      responses:
        "200":
          description: Pre-signed upload URL created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateUploadResponse"
        "400":
          description: Invalid request body or unsupported `contentType`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UploadFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
        "413":
          description: Upload exceeds the maximum allowed size.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UploadFailureResponse"
      security:
        - apiKey: []
  /v1/uploads/{emailAssetId}/complete:
    parameters:
      - name: emailAssetId
        in: path
        required: true
        description: The `emailAssetId` returned when the upload was created via `POST
          /v1/uploads`.
        schema:
          type: string
          examples:
            - cla3s5s7e9t1i3d5f7g9h1j3
    post:
      operationId: completeUpload
      tags:
        - Uploads
      summary: Complete an upload
      description: Finalize an image upload after the file has been uploaded to the
        pre-signed URL. Returns the public URL of the uploaded image asset.
      x-mint:
        href: /api-reference/complete-upload
        metadata:
          description: Finalize an image upload after the file has been uploaded to the
            pre-signed URL.
      responses:
        "200":
          description: Upload completed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CompleteUploadResponse"
        "400":
          description: Upload id is missing or the uploaded file has an unsupported
            content type.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UploadFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Upload not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UploadFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "429":
          description: Upload limit exceeded.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UploadLimitExceededFailureResponse"
      security:
        - apiKey: []
  /v1/workflows:
    get:
      tags:
        - Workflows
      summary: List workflows
      operationId: listWorkflows
      description: Retrieve a paginated list of workflows.
      x-mint:
        href: /api-reference/list-workflows
      parameters:
        - name: perPage
          in: query
          required: false
          description: How many results to return in each request. Must be between 10 and
            50. Default is 20.
          schema:
            type: string
        - name: cursor
          in: query
          required: false
          description: A cursor to return a specific page of results. Cursors can be found
            from the `pagination.nextCursor` value in each response.
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListWorkflowsResponse"
        "400":
          description: Invalid `perPage` or `cursor` value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "401":
          description: Invalid API key.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      tags:
        - Workflows
      summary: Create a workflow
      operationId: createWorkflow
      description: Create a draft workflow with a blank trigger and exit node.
      x-mint:
        href: /api-reference/create-workflow
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateWorkflowRequest"
      responses:
        "200":
          description: Workflow created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SimplifiedWorkflow"
        "400":
          description: Invalid request body.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "401":
          description: Invalid API key.
        "405":
          description: Wrong HTTP request method.
        "500":
          description: Workflow creation is unavailable for this team.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
      security:
        - apiKey: []
  /v1/workflows/{workflowId}:
    parameters:
      - name: workflowId
        in: path
        required: true
        description: The ID of the workflow.
        schema:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
    get:
      tags:
        - Workflows
      summary: Get a workflow
      operationId: getWorkflow
      description: Retrieve a workflow graph with node type names, connections, and
        selected display fields.
      x-mint:
        content: Returns a simplified view of the workflow graph. Each node includes its
          `typeName`, outgoing connections in `nextNodeIds`, and selected
          display fields. Use [Get a workflow
          node](/api-reference/get-workflow-node) to retrieve full details for a
          single node.
        href: /api-reference/get-workflow
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SimplifiedWorkflow"
        "400":
          description: Invalid `workflowId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "401":
          description: Invalid API key.
        "404":
          description: Workflow not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      tags:
        - Workflows
      summary: Update a workflow
      operationId: updateWorkflowProperties
      description: Update a workflow's display properties. At least one property must
        be provided. To change the workflow's mailing list, use the `POST
        /v1/workflows/{workflowId}/mailing-list` endpoint instead.
      x-mint:
        href: /api-reference/update-workflow
        content: <Info>To change a workflow's mailing list, use the [Change workflow
          mailing list](/api-reference/change-workflow-mailing-list) endpoint
          instead. This is because changing mailing lists may remove queued
          contacts from the workflow.</Info>
        metadata:
          description: Update a workflow's display properties.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateWorkflowPropertiesRequest"
      responses:
        "200":
          description: Workflow properties updated.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SimplifiedWorkflow"
        "400":
          description: Invalid `workflowId` or request body.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "401":
          description: Invalid API key.
        "404":
          description: Workflow not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: "`expectedRevisionId` is stale."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
      security:
        - apiKey: []
    delete:
      tags:
        - Workflows
      summary: Delete a workflow
      operationId: deleteWorkflow
      description: "Delete a workflow. Successful deletion returns `204 No Content`.
        If the workflow is currently sending or has queued contacts, Loops
        returns `409 Conflict` with a message instead of deleting. Retry with
        `confirmDelete: true` to delete the workflow, stop sending, and cancel
        queued contacts."
      x-mint:
        href: /api-reference/delete-workflow
        content: >-
          Deleting a sending workflow stops sending it. Additionally, if the
          workflow has queued contacts, they are removed.


          Successful deletion returns `204 No Content`. If the workflow is
          currently sending or has queued contacts, Loops returns `409 Conflict`
          with a `message` instead of deleting. Retry the request with the same
          `expectedRevisionId` and `confirmDelete: true` to delete the workflow.


          Once deleted, workflows are not returned in other API endpoints.
        metadata:
          sidebarTitle: Delete a workflow
          description: Delete a workflow with revision and confirmation handling.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DeleteWorkflowRequest"
      responses:
        "204":
          description: Workflow deleted. No response body.
        "400":
          description: Invalid `workflowId`, request body, or delete target.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "401":
          description: Invalid API key.
        "404":
          description: Workflow not found. Deleted workflows are returned as not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: "`expectedRevisionId` is stale, or workflow deletion requires
            confirmation because the workflow is currently sending or has queued
            contacts."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
              examples:
                staleRevision:
                  summary: "`expectedRevisionId` is stale"
                  value:
                    message: workflowRevisionId mismatch. Latest workflowRevisionId is
                      clx7a3b5c7d9e1f3g5h7i9j1. Refetch and retry.
                confirmationRequiredSending:
                  summary: Workflow is currently sending
                  value:
                    message: "This workflow is currently sending. Deleting it will stop sending it.
                      Confirm deletion by sending a second request with
                      confirmDelete: true."
                confirmationRequiredQueuedContacts:
                  summary: Workflow has queued contacts
                  value:
                    message: "This workflow has 3 queued contacts. Deleting it will cancel those
                      queued contacts. Confirm deletion by sending a second
                      request with confirmDelete: true."
                confirmationRequiredSendingAndQueuedContacts:
                  summary: Workflow is sending and has queued contacts
                  value:
                    message: "This workflow is currently sending and has 3 queued contacts. Deleting
                      it will stop sending it and cancel those queued contacts.
                      Confirm deletion by sending a second request with
                      confirmDelete: true."
      security:
        - apiKey: []
  /v1/workflows/{workflowId}/mailing-list:
    parameters:
      - name: workflowId
        in: path
        required: true
        description: The ID of the workflow.
        schema:
          type: string
    post:
      tags:
        - Workflows
      summary: Change workflow mailing list
      operationId: changeWorkflowMailingList
      description: 'Dry run or apply a workflow mailing list change. If queued
        contacts would be removed from the workflow due to the change of mailing
        list, Loops returns with `"status": "queuedContactsFound"` instead of
        applying the change. Retry with `queuedContactPolicy: "discard"` to
        apply the change and discard those contacts. Confirmed update responses
        include the simplified workflow after the mailing list changes.'
      x-mint:
        href: /api-reference/change-workflow-mailing-list
        content: >-
          Use this endpoint to change a workflow's mailing list.


          Make a dry run request using `dryRun: true`.


          If queued contacts would be removed from the workflow due to the
          change of mailing list, Loops returns with `"status":
          "queuedContactsFound"` instead of applying the change. Retry with
          `queuedContactPolicy: "discard"` to apply the change and discard those
          contacts.


          Confirmed update responses include the simplified workflow after the
          mailing list changes.
        metadata:
          sidebarTitle: Change mailing list
          description: Change a workflow's mailing list.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ChangeWorkflowMailingListRequest"
      responses:
        "200":
          description: Mailing-list dry run, queued-contact warning, or update result.
            Confirmed update responses include the simplified workflow after the
            mailing list changes.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ChangeWorkflowMailingListResponse"
        "400":
          description: Invalid `workflowId`, request body, mailing list, or workflow state.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "401":
          description: Invalid API key.
        "404":
          description: Workflow not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: "`expectedRevisionId` is stale."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
      security:
        - apiKey: []
  /v1/workflows/{workflowId}/nodes:
    parameters:
      - name: workflowId
        in: path
        required: true
        description: The ID of the workflow.
        schema:
          type: string
    post:
      tags:
        - Workflow nodes
      summary: Create a workflow node
      operationId: createWorkflowNode
      description: >-
        Create a new default workflow node and return it with the latest
        workflow.


        Choose where the node goes with `insertMode`: `between` places it
        between an existing `fromNodeId` -> `toNodeId` connection, `before`
        places it before `toNodeId`, and `after` places it after `fromNodeId`
        when that node has exactly one outgoing connection. `after` is a
        convenience for simple linear paths, so callers do not need to fetch and
        pass the current child node ID. It is invalid when `fromNodeId` has no
        outgoing nodes, multiple outgoing nodes, or is an exit node. When the
        source has multiple outgoing nodes, use `between` with the exact
        `toNodeId` instead. For `before`, deprecated `beforeNodeId` requests are
        still accepted for compatibility, but new callers should use `toNodeId`.


        New nodes start with default settings; update the node after creation to
        configure it. Branch nodes create their default paths too: `BranchNode`
        creates two `AudienceFilter` children, and `ExperimentBranchNode`
        creates two regular `VariantNode` children plus one control
        `VariantNode`. Public workflows can have up to 400 nodes. Generated
        children count toward that limit, so a normal create adds 1 node,
        `BranchNode` adds 3, and `ExperimentBranchNode` adds 4. To add a sibling
        child path to a branch or experiment branch, use the `POST
        /v1/workflows/{workflowId}/nodes/{nodeId}/add-branch` endpoint. Branch
        paths can be edited with create-node, but a workflow cannot be started
        unless each direct `BranchNode` child is an `AudienceFilter`. For
        experiments, use create-node only to insert a missing `VariantNode`
        before non-variant content; use add-branch for another variant path.
      x-mint:
        href: /api-reference/create-workflow-node
        content: >-
          Choose where the node goes with `insertMode`:

          - `between` places it between an existing `fromNodeId` -> `toNodeId`
          connection

          - `before` places it before `toNodeId`

          - `after` places it after `fromNodeId` when that node has exactly one
          outgoing connection.


          Use `after` for simple linear paths when you do not want to fetch and
          pass the current child node ID. `after` is invalid when `fromNodeId`
          has no outgoing nodes, multiple outgoing nodes, or is an exit node.
          When the source has multiple outgoing nodes, use `between` with the
          exact `toNodeId` instead. For `before`, deprecated `beforeNodeId`
          requests are still accepted for compatibility, but new callers should
          use `toNodeId`.


          New nodes start with default settings; update the node after creation
          to configure it. Branch nodes create their default paths too:
          `BranchNode` creates two `AudienceFilter` children, and
          `ExperimentBranchNode` creates two regular `VariantNode` children plus
          one control `VariantNode`.


          Public workflows can have up to 400 nodes. Generated children count
          toward that limit, so a normal create adds 1 node, `BranchNode` adds
          3, and `ExperimentBranchNode` adds 4. To add a sibling child path to a
          branch or experiment branch, use the `POST
          /v1/workflows/{workflowId}/nodes/{nodeId}/add-branch` endpoint. Branch
          paths can be edited with create-node, but a workflow cannot be started
          unless each direct `BranchNode` child is an `AudienceFilter`. For
          experiments, use create-node only to insert a missing `VariantNode`
          before non-variant content; use add-branch for another variant path.
        metadata:
          sidebarTitle: Create a node
          description: Create a new default workflow node and return it with the latest
            workflow
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateWorkflowNodeRequest"
      responses:
        "200":
          description: Workflow node created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateWorkflowNodeResponse"
        "400":
          description: Invalid request. Details will be shown in `message`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "401":
          description: Invalid API key.
        "404":
          description: Workflow or workflow node not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: "`expectedRevisionId` is stale."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
      security:
        - apiKey: []
  /v1/workflows/{workflowId}/nodes/{nodeId}/add-branch:
    parameters:
      - name: workflowId
        in: path
        required: true
        description: The ID of the workflow.
        schema:
          type: string
      - name: nodeId
        in: path
        required: true
        description: The ID of the BranchNode or ExperimentBranchNode that should
          receive one new child.
        schema:
          type: string
    post:
      tags:
        - Workflow nodes
      summary: Add a branch
      operationId: addWorkflowBranch
      description: >-
        Add a branch and a child node under an existing Branch or Experiment
        node. Returns the created child node plus the latest workflow.


        - Adding a branch to a `BranchNode` creates one `AudienceFilter` child
        node.

        - Adding a branch to an `ExperimentBranchNode` creates one `VariantNode`
        child node.


        This endpoint does not accept node configuration fields; update the
        child node with `POST /v1/workflows/{workflowId}/nodes/{nodeId}` after
        creation. Public workflows are limited to 400 nodes, and this endpoint
        adds 1 node.
      x-mint:
        href: /api-reference/add-workflow-branch
        content: >-
          Adding a branch to a `BranchNode` creates one `AudienceFilter` child
          node.

          Adding a branch to an `ExperimentBranchNode` creates one `VariantNode`
          child node.


          This endpoint does not accept node configuration fields; [update the
          child node](/api-reference/update-workflow-node) after creation.
          Public workflows are limited to 400 nodes, and this endpoint adds 1
          node.
        metadata:
          sidebarTitle: Add a branch
          description: Add a branch and a child node under an existing Branch or
            Experiment node.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AddWorkflowBranchRequest"
      responses:
        "200":
          description: Branch added.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AddWorkflowBranchResponse"
        "400":
          description: Invalid `workflowId`, `nodeId`, request body, branch target,
            workflow state, or workflow node cap.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "401":
          description: Invalid API key.
        "404":
          description: Workflow or workflow node not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: "`expectedRevisionId` is stale."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
      security:
        - apiKey: []
  /v1/workflows/{workflowId}/nodes/{nodeId}:
    parameters:
      - name: workflowId
        in: path
        required: true
        description: The ID of the workflow.
        schema:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
      - name: nodeId
        in: path
        required: true
        description: The ID of the workflow node.
        schema:
          type: string
          examples:
            - cln8p0q2r4s6t8u0v2w4x6z8
    get:
      tags:
        - Workflow nodes
      summary: Get a workflow node
      operationId: getWorkflowNode
      description: Retrieve detailed data for a single workflow node.
      x-mint:
        href: /api-reference/get-workflow-node
        metadata:
          sidebarTitle: Get a node
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowNodeWithRevision"
        "400":
          description: Invalid `workflowId` or `nodeId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "401":
          description: Invalid API key.
        "404":
          description: Workflow or workflow node not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      tags:
        - Workflow nodes
      summary: Update a workflow node
      operationId: updateWorkflowNode
      description: Update workflow-node-owned fields for a single node. Shared
        resources such as email messages and audience segments should be updated
        through their own APIs.
      x-mint:
        href: /api-reference/update-workflow-node
        content: Shared resources such as email messages and audience segments should be
          updated through their own APIs.
        metadata:
          sidebarTitle: Update a node
          description: Update workflow-node-owned fields for a single node.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateWorkflowNodeRequest"
      responses:
        "200":
          description: Workflow node updated.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UpdateWorkflowNodeResponse"
        "400":
          description: Invalid `workflowId`, `nodeId`, request body, or node update.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "401":
          description: Invalid API key.
        "404":
          description: Workflow or workflow node not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: "`expectedRevisionId` is stale."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "501":
          description: This node update is not implemented.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
      security:
        - apiKey: []
    delete:
      tags:
        - Workflow nodes
      summary: Delete a workflow node
      operationId: deleteWorkflowNode
      description: 'Delete a single workflow node. If contacts are queued at the node,
        Loops returns with `"status": "queuedContactsFound"` instead of
        deleting. Retry with `queuedContactPolicy: "discard"` to delete the node
        and discard those queued contacts. Confirmed deletion responses include
        the simplified workflow after the node is removed.'
      x-mint:
        href: /api-reference/delete-workflow-node
        content: >-
          Delete a node from a workflow.


          Make a dry run request using `dryRun: true`.


          If contacts are queued at the node, Loops returns with `"status":
          "queuedContactsFound"` instead of deleting. Retry with
          `queuedContactPolicy: "discard"` to delete the node and discard those
          queued contacts.


          Confirmed deletion responses include the simplified workflow after the
          node is removed.
        metadata:
          sidebarTitle: Delete a node
          description: Delete a single workflow node.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DeleteWorkflowNodeRequest"
      responses:
        "200":
          description: Delete dry run, queued-contact warning, or deletion result.
            Confirmed deletion responses include the simplified workflow after
            the node is removed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeleteWorkflowNodeResponse"
        "400":
          description: Invalid `workflowId`, `nodeId`, request body, or delete target.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "401":
          description: Invalid API key.
        "404":
          description: Workflow or workflow node not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: "`expectedRevisionId` is stale."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
      security:
        - apiKey: []
  /v1/workflows/{workflowId}/nodes/{nodeId}/reroute:
    parameters:
      - name: workflowId
        in: path
        required: true
        description: The ID of the workflow.
        schema:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
      - name: nodeId
        in: path
        required: true
        description: The ID of the source workflow node whose outgoing connection should
          be moved.
        schema:
          type: string
          examples:
            - cln1a3b5c7d9e1f3g5h7i9j1
    post:
      tags:
        - Workflow nodes
      summary: Reroute a node connection
      operationId: rerouteNodeConnection
      description: Reroute the source node's existing connection to another valid
        target node. Returns the updated source node and the latest workflow.
      x-mint:
        href: /api-reference/reroute-node-connection
        content: >-
          Use this endpoint to modify an existing node connection to another
          target. Send the source node in the URL path and the new target in the
          request body.


          The source node must have exactly one outgoing connection. Branch and
          experiment branch nodes cannot be rerouted with this endpoint because
          they have multiple branch-specific outputs. The current target must
          still have another incoming connection after the reroute, and the new
          target must be valid for the source node. The workflow cannot be
          edited while in a `SENDING` state.
        metadata:
          sidebarTitle: Reroute a node
          description: Reroute one existing node connection to another valid target node.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RerouteNodeConnectionRequest"
      responses:
        "200":
          description: Node connection rerouted.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RerouteNodeConnectionResponse"
        "400":
          description: Invalid `workflowId`, `nodeId`, request body, node connection
            selection, reroute target, or workflow state.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "401":
          description: Invalid API key.
        "404":
          description: Workflow or workflow node not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: "`expectedRevisionId` is stale."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
      security:
        - apiKey: []
  /v1/workflows/{workflowId}/nodes/{nodeId}/recursive:
    parameters:
      - name: workflowId
        in: path
        required: true
        description: The ID of the workflow.
        schema:
          type: string
      - name: nodeId
        in: path
        required: true
        description: The root node ID of the subtree to delete.
        schema:
          type: string
    delete:
      tags:
        - Workflow nodes
      summary: Delete workflow nodes recursively
      operationId: deleteWorkflowNodeRecursively
      description: 'Delete a node and its downstream subtree. If contacts are queued
        at any node that would be deleted, Loops returns with `"status":
        "queuedContactsFound"` instead of deleting. Retry with
        `queuedContactPolicy: "discard"` to delete the nodes and discard those
        queued contacts. Confirmed deletion responses include the simplified
        workflow after the nodes are removed.'
      x-mint:
        href: /api-reference/delete-workflow-nodes
        content: >-
          Delete a node and its downstream subtree.


          Make a dry run request using `dryRun: true`.


          If contacts are queued at any node that would be deleted, Loops
          returns with `"status": "queuedContactsFound"` instead of deleting.
          Retry with `queuedContactPolicy: "discard"` to delete the nodes and
          discard those queued contacts.


          Confirmed deletion responses include the simplified workflow after the
          nodes are removed.
        metadata:
          sidebarTitle: Delete nodes
          description: Delete a node and its downstream subtree.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DeleteWorkflowNodeRequest"
      responses:
        "200":
          description: Delete dry run, queued-contact warning, or deletion result.
            Confirmed deletion responses include the simplified workflow after
            the nodes are removed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeleteWorkflowNodeResponse"
        "400":
          description: Invalid `workflowId`, `nodeId`, request body, or delete target.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "401":
          description: Invalid API key.
        "404":
          description: Workflow or workflow node not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: "`expectedRevisionId` is stale."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowFailureResponse"
      security:
        - apiKey: []
webhooks:
  contactUnsubscribed:
    post:
      operationId: webhookContactUnsubscribed
      x-excluded: true
      summary: Contact unsubscribed
      description: Sent when a contact is unsubscribed from your audience, or when a
        contact is deleted from your audience (alongside `contact.deleted`).
        This is not the same as a contact unsubscribing from a mailing list (see
        `contact.mailingList.unsubscribed`). Contains a `contactIdentity`
        object.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookContactUnsubscribedPayload"
            example:
              eventName: contact.unsubscribed
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  contactCreated:
    post:
      operationId: webhookContactCreated
      x-excluded: true
      summary: Contact created
      description: Sent when a new contact is created in your audience. Contains a
        `contactIdentity` object and a full `contact` object with all of the new
        contact's properties (including custom properties). When double opt-in
        is enabled, contact webhooks do not fire until the contact is confirmed;
        `contact.created` only fires for form-created contacts once they confirm
        their subscription. `optInStatus` will never be `"pending"` or
        `"rejected"` for this event.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookContactCreatedPayload"
            example:
              eventName: contact.created
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              contactIdentity:
                id: cm4itta800003ow9hhekzk94o
                email: test+5@loops.so
                userId: null
              contact:
                id: cm4itta800003ow9hhekzk94o
                email: test+5@loops.so
                firstName: null
                lastName: null
                source: API
                subscribed: true
                userGroup: ""
                userId: null
                mailingLists:
                  cm4ittp2k000l12j3lgrzvlxt: true
                optInStatus: accepted
                favoriteColor: blue
                favoriteNumber: 42
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  contactDeleted:
    post:
      operationId: webhookContactDeleted
      x-excluded: true
      summary: Contact deleted
      description: Sent when a contact is deleted from your audience. Contains a
        `contactIdentity` object.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookContactDeletedPayload"
            example:
              eventName: contact.deleted
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  contactMailingListSubscribed:
    post:
      operationId: webhookContactMailingListSubscribed
      x-excluded: true
      summary: Contact subscribed to mailing list
      description: Sent when a contact is subscribed to a mailing list. Contains
        `contactIdentity` and `mailingList` objects. When double opt-in is
        enabled, this event only fires after the contact confirms their
        subscription.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookContactMailingListSubscribedPayload"
            example:
              eventName: contact.mailingList.subscribed
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
              mailingList:
                id: cm4ittp2k000l12j3lgrzvlxt
                name: test mailing list
                description: null
                isPublic: true
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  contactMailingListUnsubscribed:
    post:
      operationId: webhookContactMailingListUnsubscribed
      x-excluded: true
      summary: Contact unsubscribed from mailing list
      description: Sent when a contact is unsubscribed from a mailing list. This is
        not the same as a contact unsubscribing from your audience (see
        `contact.unsubscribed`). Contains `contactIdentity` and `mailingList`
        objects.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookContactMailingListUnsubscribedPayload"
            example:
              eventName: contact.mailingList.unsubscribed
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
              mailingList:
                id: cm4ittp2k000l12j3lgrzvlxt
                name: test mailing list
                description: null
                isPublic: true
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  transactionalEmailSent:
    post:
      operationId: webhookTransactionalEmailSent
      x-excluded: true
      summary: Transactional email sent
      description: Sent when a transactional email is sent to a contact. Contains a
        `transactionalId` value plus `contactIdentity` and `email` objects.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookTransactionalEmailSentPayload"
            example:
              eventName: transactional.email.sent
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
              transactionalId: cm4t1suns001uw6atri87v54s
              transactionalName: Test Transactional
              email:
                id: cm4t1sseg004tje7982991nan
                emailMessageId: cm4ittv1v001oow9hruou8na8
                subject: Subject of the email
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  campaignEmailSent:
    post:
      operationId: webhookCampaignEmailSent
      x-excluded: true
      summary: Campaign email sent
      description: Sent when a campaign email is sent to a contact. This event fires
        for every campaign send (for example, sending to 1,000 contacts produces
        1,000 events). Contains `campaignId` and `campaignName` plus
        `contactIdentity` and `email` objects. If the campaign was sent to one
        or more mailing lists, a `mailingLists` array is also included.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookCampaignEmailSentPayload"
            example:
              eventName: campaign.email.sent
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
              campaignId: cm4t1suns001uw6atri87v54s
              campaignName: Test Campaign
              email:
                id: cm4t1sv84004yje79hawr1fi1
                emailMessageId: cm4t1suns001ww6atotin3bn1
                subject: Test Subject
              mailingLists:
                - id: cm4ittp2k000l12j3lgrzvlxt
                  name: test mailing list
                  description: null
                  isPublic: true
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  loopEmailSent:
    post:
      operationId: webhookLoopEmailSent
      x-excluded: true
      summary: Loop email sent
      description: Sent when a workflow email is sent to a contact. This event keeps
        its `loop` naming for compatibility (Loops was renamed to Workflows on
        May 6, 2026). This event fires for every contact in a workflow (for
        example, 1,000 recipients produces 1,000 events). Contains `loopId` and
        `loopName` plus `contactIdentity` and `email` objects. If the workflow
        was sent to one or more mailing lists, a `mailingLists` array is also
        included.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookLoopEmailSentPayload"
            example:
              eventName: loop.email.sent
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
              loopId: cm4t1snfj0052icemfshgqfcw
              loopName: Test Loop
              email:
                id: cm4t1socj004mje79e61mgh7d
                emailMessageId: cm4ittv1v001oow9hruou8na8
                subject: Subject of the email
              mailingLists:
                - id: cm4ittp2k000l12j3lgrzvlxt
                  name: test mailing list
                  description: null
                  isPublic: true
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  emailDelivered:
    post:
      operationId: webhookEmailDelivered
      x-excluded: true
      summary: Email delivered
      description: Sent when an email is delivered to its recipient. Contains
        `sourceType` (`campaign`, `loop`, or `transactional`) and the related
        `campaignId`, `loopId` (workflow ID), or `transactionalId`, plus
        `contactIdentity` and `email` objects.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookEmailDeliveredPayload"
            example:
              eventName: email.delivered
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              sourceType: campaign
              campaignId: cm4t1suns001uw6atri87v54s
              email:
                id: cm4t1sseg004tje7982991nan
                emailMessageId: cm4ittv1v001oow9hruou8na8
                subject: Subject of the email
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  emailSoftBounced:
    post:
      operationId: webhookEmailSoftBounced
      x-excluded: true
      summary: Email soft bounced
      description: Sent when an email soft bounces. Soft bounces are temporary
        delivery failures (for example, a connection timing out). Soft bounces
        are retried multiple times and the email may still be delivered.
        Contains `sourceType` and the related `campaignId`, `loopId` (workflow
        ID), or `transactionalId`, plus `contactIdentity` and `email` objects.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookEmailSoftBouncedPayload"
            example:
              eventName: email.softBounced
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              sourceType: campaign
              campaignId: cm4t1suns001uw6atri87v54s
              email:
                id: cm4t1sseg004tje7982991nan
                emailMessageId: cm4ittv1v001oow9hruou8na8
                subject: Subject of the email
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  emailHardBounced:
    post:
      operationId: webhookEmailHardBounced
      x-excluded: true
      summary: Email hard bounced
      description: Sent when an email hard bounces. Hard bounces are persistent
        delivery failures (for example, a mailbox that does not exist); the
        email will not be delivered. In Loops, a hard bounce also unsubscribes
        the contact from your audience, so a `contact.unsubscribed` event will
        also be sent. Contains `sourceType` and the related `campaignId`,
        `loopId` (workflow ID), or `transactionalId`, plus `contactIdentity` and
        `email` objects.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookEmailHardBouncedPayload"
            example:
              eventName: email.hardBounced
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              sourceType: campaign
              campaignId: cm4t1suns001uw6atri87v54s
              email:
                id: 9874cm4t1sseg004tje7982991nan8732843
                emailMessageId: cm4ittv1v001oow9hruou8na8
                subject: Subject of the email
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  emailClicked:
    post:
      operationId: webhookEmailClicked
      x-excluded: true
      summary: Email clicked
      description: Sent when a link in a campaign or workflow email is clicked. Not
        available for transactional emails because link clicks are not tracked
        for transactional emails. Contains `sourceType` and the related
        `campaignId` or `loopId` (workflow ID), plus `contactIdentity` and
        `email` objects.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookEmailClickedPayload"
            example:
              eventName: email.clicked
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              sourceType: campaign
              campaignId: cm4t1suns001uw6atri87v54s
              email:
                id: cm4t1sseg004tje7982991nan
                emailMessageId: cm4ittv1v001oow9hruou8na8
                subject: Subject of the email
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  emailUnsubscribed:
    post:
      operationId: webhookEmailUnsubscribed
      x-excluded: true
      summary: Email unsubscribed
      description: Sent when a recipient unsubscribes from marketing email or a
        mailing list using an email's "Unsubscribe" link. A
        `contact.unsubscribed` or `contact.mailingList.unsubscribed` event will
        also be sent depending on whether the email was sent to a mailing list.
        Not available for transactional emails because unsubscribe links are not
        included for transactional emails. Contains `sourceType` and the related
        `campaignId` or `loopId` (workflow ID), plus `contactIdentity` and
        `email` objects.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookEmailUnsubscribedPayload"
            example:
              eventName: email.unsubscribed
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              sourceType: campaign
              campaignId: cm4t1suns001uw6atri87v54s
              email:
                id: cm4t1sseg004tje7982991nan
                emailMessageId: cm4ittv1v001oow9hruou8na8
                subject: Subject of the email
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  emailResubscribed:
    post:
      operationId: webhookEmailResubscribed
      x-excluded: true
      summary: Email resubscribed
      description: Sent when a recipient resubscribes to marketing email from an
        email's preference center ("Unsubscribe" link). Not available for
        transactional emails because unsubscribe links are not included for
        transactional emails. Contains `sourceType` and the related `campaignId`
        or `loopId` (workflow ID), plus `contactIdentity` and `email` objects.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookEmailResubscribedPayload"
            example:
              eventName: email.resubscribed
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              sourceType: campaign
              campaignId: cm4t1suns001uw6atri87v54s
              email:
                id: cm4t1sseg004tje7982991nan
                emailMessageId: cm4ittv1v001oow9hruou8na8
                subject: Subject of the email
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  emailOpened:
    post:
      operationId: webhookEmailOpened
      x-excluded: true
      summary: Email opened
      description: Sent when a campaign or workflow email is opened. Not available for
        transactional emails because email opens are not tracked for
        transactional emails. Contains `sourceType` and the related `campaignId`
        or `loopId` (workflow ID), plus `contactIdentity` and `email` objects.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookEmailOpenedPayload"
            example:
              eventName: email.opened
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              sourceType: campaign
              campaignId: cm4t1suns001uw6atri87v54s
              email:
                id: cm4t1sseg004tje7982991nan
                emailMessageId: cm4ittv1v001oow9hruou8na8
                subject: Subject of the email
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  emailSpamReported:
    post:
      operationId: webhookEmailSpamReported
      x-excluded: true
      summary: Email spam reported
      description: Sent when a recipient reports your email as spam. Contains
        `sourceType` and the related `campaignId`, `loopId` (workflow ID), or
        `transactionalId`, plus `contactIdentity` and `email` objects.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookEmailSpamReportedPayload"
            example:
              eventName: email.spamReported
              eventTime: 1734425918
              webhookSchemaVersion: 1.0.0
              sourceType: campaign
              campaignId: cm4t1suns001uw6atri87v54s
              email:
                id: cm4t1sseg004tje7982991nan
                emailMessageId: cm4ittv1v001oow9hruou8na8
                subject: Subject of the email
              contactIdentity:
                id: cm4ittmhq0011ow9h6fb460yw
                email: test@example.com
                userId: null
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
  testingTestEvent:
    post:
      operationId: webhookTestingTestEvent
      x-excluded: true
      summary: Test event
      description: Test event that can be triggered from the Webhooks settings page in
        Loops. Use this to verify that your endpoint is working and that your
        signature verification code is correct. The payload contains
        `eventName`, `eventTime`, `message` (always `"test"`), and
        `webhookSchemaVersion`.
      tags:
        - Webhooks
      parameters:
        - $ref: "#/components/parameters/WebhookId"
        - $ref: "#/components/parameters/WebhookTimestamp"
        - $ref: "#/components/parameters/WebhookSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookTestingTestEventPayload"
            example:
              eventName: testing.testEvent
              eventTime: 1734425918
              message: test
              webhookSchemaVersion: 1.0.0
      responses:
        "200":
          description: Webhook received successfully. Return any 2xx status code to
            acknowledge delivery.
      security: []
components:
  schemas:
    Contact:
      type: object
      properties:
        id:
          type: string
          description: The contact's Loops ID.
          examples:
            - clh3k9m2p4q6r8s0t2v4x6z8
        email:
          type: string
          description: The contact's email address.
          examples:
            - alex@company.com
        firstName:
          type:
            - string
            - "null"
          description: The contact's first name.
          examples:
            - Alex
        lastName:
          type:
            - string
            - "null"
          description: The contact's last name.
          examples:
            - Rivera
        source:
          type: string
          description: The source the contact was created from.
          examples:
            - API
        subscribed:
          type: boolean
          description: Whether the contact will receive campaign and workflow emails.
          examples:
            - true
        userGroup:
          type: string
          description: The contact's user group.
          examples:
            - customers
        userId:
          type:
            - string
            - "null"
          description: The contact's unique user ID.
          examples:
            - usr_7f8e9d0c1b2a
        mailingLists:
          type: object
          description: Mailing lists the contact is subscribed to, represented by
            key-value pairs of mailing list IDs and `true`.
          examples:
            - cm06f5v0e45nf0ml5754o9cix: true
        optInStatus:
          type:
            - string
            - "null"
          description: Double opt-in status. This will be `null` for contacts unless they
            are created via a form while double opt-in is enabled.
          enum:
            - accepted
            - pending
            - rejected
            - null
          examples:
            - accepted
      examples:
        - id: clh3k9m2p4q6r8s0t2v4x6z8
          email: alex@company.com
          firstName: Alex
          lastName: Rivera
          source: API
          subscribed: true
          userGroup: customers
          userId: usr_7f8e9d0c1b2a
          mailingLists:
            clm2k8j4h6g0f8d6s4a2b0z8: true
          optInStatus: accepted
    ContactFields:
      type: object
      properties:
        email:
          type: string
          examples:
            - alex@company.com
          description: The contact's email address.
        firstName:
          type: string
          description: The contact's first name.
          examples:
            - Alex
        lastName:
          type: string
          description: The contact's last name.
          examples:
            - Rivera
        source:
          type: string
          description: A custom source value to replace the default “API”.
          examples:
            - API
        subscribed:
          type: boolean
          description: Whether the contact will receive campaign and workflow emails. All
            new contacts are subscribed by default.
        userGroup:
          type: string
          description: The contact's user group.
          examples:
            - customers
        userId:
          type: string
          description: A unique user ID (for example, from an external application).
          examples:
            - usr_7f8e9d0c1b2a
        mailingLists:
          $ref: "#/components/schemas/MailingListSubscriptions"
      additionalProperties:
        oneOf:
          - type: string
          - type: number
          - type: boolean
      examples:
        - email: alex@company.com
          firstName: Alex
          lastName: Rivera
          subscribed: true
          userGroup: customers
          userId: usr_7f8e9d0c1b2a
          mailingLists:
            clm2k8j4h6g0f8d6s4a2b0z8: true
          favoriteColor: blue
    ContactRequest:
      allOf:
        - $ref: "#/components/schemas/ContactFields"
        - type: object
          required:
            - email
    ContactUpdateRequest:
      allOf:
        - $ref: "#/components/schemas/ContactFields"
        - type: object
          properties:
            email:
              type: string
              description: The contact's email address. **Required if `userId` is not
                provided.**
            subscribed:
              type: boolean
              description: Whether the contact will receive campaign and workflow emails. We
                recommend leaving this field out of your update requests unless
                you specifically want to unsubscribe (`false`) or re-subscribe
                (`true`) a contact. All new contacts are subscribed by default.
            userId:
              type: string
              description: The contact's unique user ID. **Required if `email` is not
                provided.**
          anyOf:
            - required:
                - email
            - required:
                - userId
      additionalProperties:
        oneOf:
          - type: string
          - type: number
          - type: boolean
      examples:
        - email: alex@company.com
          firstName: Alex
          lastName: Rivera
          subscribed: true
          userGroup: customers
          userId: usr_7f8e9d0c1b2a
          mailingLists:
            clm2k8j4h6g0f8d6s4a2b0z8: true
          favoriteColor: blue
    ContactSuccessResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - true
        id:
          type: string
          examples:
            - clh3k9m2p4q6r8s0t2v4x6z8
      required:
        - success
        - id
      examples:
        - success: true
          id: clh3k9m2p4q6r8s0t2v4x6z8
    ContactFailureResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
          examples:
            - Invalid email address.
      required:
        - success
        - message
      examples:
        - success: false
          message: Invalid email address.
    ContactDeleteRequest:
      type: object
      properties:
        email:
          type: string
          description: The contact's email address. Provide this or `userId`, not both.
          examples:
            - alex@company.com
        userId:
          type: string
          description: The contact's unique user ID. Provide this or `email`, not both.
          examples:
            - usr_7f8e9d0c1b2a
      oneOf:
        - required:
            - email
        - required:
            - userId
      examples:
        - email: alex@company.com
        - userId: usr_7f8e9d0c1b2a
    ContactDeleteResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - true
        message:
          type: string
          examples:
            - Contact deleted.
      required:
        - success
        - message
    ContactSuppressionStatusResponse:
      type: object
      properties:
        contact:
          type: object
          properties:
            id:
              type: string
              description: The contact's Loops ID.
            email:
              type: string
              description: The contact's email address.
            userId:
              type:
                - string
                - "null"
              description: The contact's unique user ID.
          required:
            - id
            - email
            - userId
        isSuppressed:
          type: boolean
          description: Whether the contact is suppressed.
        removalQuota:
          $ref: "#/components/schemas/ContactSuppressionRemovalQuota"
          description: The removal quota for the contact.
      required:
        - contact
        - isSuppressed
        - removalQuota
      examples:
        - contact:
            id: clh3k9m2p4q6r8s0t2v4x6z8
            email: alex@company.com
            userId: usr_7f8e9d0c1b2a
          isSuppressed: false
          removalQuota:
            limit: 5
            remaining: 5
    ContactSuppressionRemoveResponse:
      type: object
      properties:
        success:
          type: boolean
          description: Whether the suppression removal was successful.
          examples:
            - true
        message:
          type: string
          examples:
            - Email removed from suppression list.
        removalQuota:
          $ref: "#/components/schemas/ContactSuppressionRemovalQuota"
      required:
        - success
        - message
        - removalQuota
    ContactSuppressionRemovalQuota:
      type: object
      properties:
        limit:
          type: number
          description: The number of suppression removals allowed in a rolling 30 day
            period.
          examples:
            - 100
        remaining:
          type: number
          description: The remaining number of suppression removals left in the current 30
            day period.
          examples:
            - 10
      required:
        - limit
        - remaining
    ContactPropertyCreateRequest:
      type: object
      required:
        - name
        - type
      description: There are a few [reserved
        names](https://loops.so/docs/contacts/properties#reserved-names) that
        you cannot use for contact properties.
      properties:
        name:
          type: string
          examples:
            - favoriteColor
          description: The name of the property. This should be in camelCase, like
            `planName` or `importDate`.
        type:
          type: string
          examples:
            - string
          description: The type of property.
          enum:
            - string
            - number
            - boolean
            - date
      examples:
        - name: favoriteColor
          type: string
    ContactPropertySuccessResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - true
      required:
        - success
    ContactPropertyFailureResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
          examples:
            - Property already exists.
      required:
        - success
        - message
      examples:
        - success: false
          message: Property already exists.
    EventRequest:
      type: object
      required:
        - eventName
      anyOf:
        - required:
            - email
        - required:
            - userId
      properties:
        email:
          type: string
          description: The contact's email address. **Required if `userId` is not
            provided.**
          examples:
            - alex@company.com
        userId:
          type: string
          description: The contact's unique user ID. **Required if `email` is not
            provided.**
          examples:
            - usr_7f8e9d0c1b2a
        eventName:
          type: string
          description: The name of the event.
          examples:
            - signup
        eventProperties:
          type: object
          description: An object containing event property data for the event, available
            in emails sent by the event.
          examples:
            - planName: Pro
              importDate: 2021-01-01
        mailingLists:
          $ref: "#/components/schemas/MailingListSubscriptions"
      additionalProperties:
        oneOf:
          - type: string
          - type: number
          - type: boolean
      examples:
        - email: alex@company.com
          userId: usr_7f8e9d0c1b2a
          eventName: signup
          eventProperties:
            plan: pro
          mailingLists:
            clm2k8j4h6g0f8d6s4a2b0z8: true
    EventSuccessResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - true
      required:
        - success
    EventFailureResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
          examples:
            - Contact not found.
      required:
        - success
        - message
      examples:
        - success: false
          message: Contact not found.
    TransactionalRequest:
      type: object
      required:
        - email
        - transactionalId
      properties:
        email:
          type: string
          examples:
            - alex@company.com
          description: The recipient's email address.
        transactionalId:
          type: string
          description: The ID of the transactional email to send.
          examples:
            - cll42l54f20i1la0lfooe3z12
        addToAudience:
          type: boolean
          description: If `true`, a contact will be created in your audience using the
            `email` value (if a matching contact doesn't already exist).
          examples:
            - true
        dataVariables:
          type: object
          description: >-
            An object containing data as defined by the data variables added to
            the transactional email template. Values can be of type string or
            number.


            If you have added optional data variables to your email, you can
            exclude them from the dataVariables object or set the value to "".


            If you have added an array data variable to your email, make sure to
            include an array matching the data variables you added to your array
            block.
          examples:
            - name: Chris
              passwordResetLink: https://example.com/reset-password
        attachments:
          type: array
          description: A list containing file objects to be sent along with an email
            message. Attachments must be enabled by Loops support before they
            can be used with the API.
          items:
            type: object
            required:
              - filename
              - contentType
              - data
            properties:
              filename:
                type: string
                description: The name of the file, shown in email clients.
              contentType:
                type: string
                description: The MIME type of the file.
              data:
                type: string
                description: The base64-encoded content of the file.
      examples:
        - email: alex@company.com
          transactionalId: cll42l54f20i1la0lfooe3z12
          addToAudience: true
          dataVariables:
            name: Alex
            passwordResetLink: https://app.company.com/reset/abc123
    TransactionalSuccessResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - true
      required:
        - success
    TransactionalFailureResponse:
      type: object
      properties:
        message:
          type: string
          examples:
            - Transactional email not found.
      required:
        - message
      examples:
        - message: Transactional email not found.
    TransactionalSendFailureResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
          examples:
            - "Missing required data variable(s): confirmationUrl"
      required:
        - success
        - message
      examples:
        - success: false
          message: "Missing required data variable(s): confirmationUrl"
    TransactionalFailure2Response:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
        path:
          type: string
      required:
        - success
        - message
        - path
    TransactionalFailure3Response:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
        error:
          type: object
          properties:
            path:
              type: string
            message:
              type: string
      required:
        - success
        - message
        - error
    TransactionalFailure4Response:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
        error:
          type: object
          properties:
            path:
              type: string
            reason:
              type: string
      required:
        - success
        - message
        - error
    TransactionalFailure5Response:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
        error:
          type: object
          properties:
            path:
              type: string
            message:
              type: string
        transactionalId:
          type: string
          examples:
            - cll42l54f20i1la0lfooe3z12
      required:
        - success
        - message
        - error
        - transactionalId
      examples:
        - success: false
          message: "Missing required data variable(s): confirmationUrl"
          error:
            path: dataVariables
            message: "Missing required data variable(s): confirmationUrl"
          transactionalId: cll42l54f20i1la0lfooe3z12
    IdempotencyKeyFailureResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
      required:
        - success
        - message
      examples:
        - success: false
          message: Idempotency key already used with a different request body.
    TransactionalEmail:
      type: object
      properties:
        id:
          type: string
          description: The ID of the transactional email.
        name:
          type: string
          description: The name of the transactional email.
        lastUpdated:
          type: string
          description: The date and time the transactional email was last updated in ISO
            8601 format.
        dataVariables:
          type: array
          description: The data variables used by the transactional email.
      examples:
        - id: cll42l54f20i1la0lfooe3z12
          name: Sign up confirmation
          lastUpdated: 2025-02-02T02:56:28.845Z
          dataVariables:
            - confirmationUrl
      required:
        - id
        - name
        - lastUpdated
        - dataVariables
    ListTransactionalsResponse:
      type: object
      properties:
        pagination:
          $ref: "#/components/schemas/Pagination"
        data:
          type: array
          items:
            $ref: "#/components/schemas/TransactionalEmail"
      examples:
        - pagination:
            totalResults: 2
            returnedResults: 2
            perPage: 20
            totalPages: 1
            nextCursor: null
            nextPage: null
          data:
            - id: cll42l54f20i1la0lfooe3z12
              name: Sign up confirmation
              lastUpdated: 2025-06-29T07:47:39.370Z
              dataVariables:
                - confirmationUrl
    TransactionalResource:
      type: object
      properties:
        id:
          type: string
          description: The ID of the transactional email.
          examples:
            - cll42l54f20i1la0lfooe3z12
        url:
          type: string
          format: uri
          description: The URL of the transactional email in the Loops app.
          examples:
            - https://app.loops.so/transactional/cll42l54f20i1la0lfooe3z12
        name:
          type: string
          description: The name of the transactional email.
          examples:
            - Sign up confirmation
        draftEmailMessageId:
          type:
            - string
            - "null"
          description: The ID of the draft email message. `null` if there is no draft
            version.
          examples:
            - cle5f7g9h1i3j5k7l9m1n3p5
        publishedEmailMessageId:
          type:
            - string
            - "null"
          description: The ID of the published email message. `null` if there is no
            published version.
          examples:
            - cle5f7g9h1i3j5k7l9m1n3p5
        transactionalGroupId:
          type:
            - string
            - "null"
          description: The ID of the group this transactional email belongs to.
          examples:
            - clg7n5p3q1r9s7t5u3v1w9y7
        createdAt:
          type: string
          format: date-time
          description: ISO 8601 timestamp for when the transactional email was created.
          examples:
            - 2025-06-29T07:47:39.370Z
        updatedAt:
          type: string
          format: date-time
          description: ISO 8601 timestamp for when the transactional email was last updated.
          examples:
            - 2025-06-29T07:47:39.370Z
        dataVariables:
          type: array
          description: Data variable names used by the published email. Empty for
            unpublished transactional emails.
          items:
            type: string
      required:
        - id
        - url
        - name
        - draftEmailMessageId
        - publishedEmailMessageId
        - transactionalGroupId
        - createdAt
        - updatedAt
        - dataVariables
      examples:
        - id: cll42l54f20i1la0lfooe3z12
          url: https://app.loops.so/transactional/cll42l54f20i1la0lfooe3z12
          name: Sign up confirmation
          draftEmailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
          publishedEmailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
          transactionalGroupId: clg7n5p3q1r9s7t5u3v1w9y7
          createdAt: 2025-06-29T07:47:39.370Z
          updatedAt: 2025-06-29T07:47:39.370Z
          dataVariables:
            - confirmationUrl
    TransactionalDraftResponse:
      type: object
      properties:
        id:
          type: string
          description: The ID of the transactional email.
        url:
          type: string
          format: uri
          description: The URL of the transactional email in the Loops app.
          examples:
            - https://app.loops.so/transactional/cll42l54f20i1la0lfooe3z12
        name:
          type: string
          description: The name of the transactional email.
        draftEmailMessageId:
          type:
            - string
            - "null"
          description: The ID of the draft email message.
        draftEmailMessageContentRevisionId:
          type:
            - string
            - "null"
          description: The `contentRevisionId` of the draft email message. Pass this as
            `expectedRevisionId` on your first update via `POST
            /v1/email-messages/{emailMessageId}`.
          examples:
            - clrev1s10n2i3d4e5f6g7h8
        publishedEmailMessageId:
          type:
            - string
            - "null"
          description: The ID of the published email message. `null` if there is no
            published version.
        transactionalGroupId:
          type:
            - string
            - "null"
          description: The ID of the group this transactional email belongs to. Returned
            when creating a transactional email.
        createdAt:
          type: string
          format: date-time
          description: ISO 8601 timestamp for when the transactional email was created.
        updatedAt:
          type: string
          format: date-time
          description: ISO 8601 timestamp for when the transactional email was last updated.
        dataVariables:
          type: array
          description: Data variable names used by the published email. Empty for
            unpublished transactional emails.
          items:
            type: string
      required:
        - id
        - url
        - name
        - draftEmailMessageId
        - draftEmailMessageContentRevisionId
        - publishedEmailMessageId
        - createdAt
        - updatedAt
        - dataVariables
      examples:
        - id: cll42l54f20i1la0lfooe3z12
          url: https://app.loops.so/transactional/cll42l54f20i1la0lfooe3z12
          name: Sign up confirmation
          draftEmailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
          publishedEmailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
          transactionalGroupId: clg7n5p3q1r9s7t5u3v1w9y7
          createdAt: 2025-06-29T07:47:39.370Z
          updatedAt: 2025-06-29T07:47:39.370Z
          dataVariables:
            - confirmationUrl
          draftEmailMessageContentRevisionId: clrev1s10n2i3d4e5f6g7h8
    ListTransactionalsResourceResponse:
      type: object
      properties:
        pagination:
          $ref: "#/components/schemas/Pagination"
        data:
          type: array
          items:
            $ref: "#/components/schemas/TransactionalResource"
      required:
        - pagination
        - data
      examples:
        - pagination:
            totalResults: 2
            returnedResults: 2
            perPage: 20
            totalPages: 1
            nextCursor: null
            nextPage: null
          data:
            - id: cll42l54f20i1la0lfooe3z12
              url: https://app.loops.so/transactional/cll42l54f20i1la0lfooe3z12
              name: Sign up confirmation
              draftEmailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
              publishedEmailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
              transactionalGroupId: clg7n5p3q1r9s7t5u3v1w9y7
              createdAt: 2025-06-29T07:47:39.370Z
              updatedAt: 2025-06-29T07:47:39.370Z
              dataVariables:
                - confirmationUrl
    CreateTransactionalRequest:
      type: object
      properties:
        name:
          type: string
          description: The name of the transactional email.
          examples:
            - Welcome email
        transactionalGroupId:
          type: string
          description: The ID of the group to add this transactional email to. Defaults to
            the team's default group when omitted.
          examples:
            - clg7n5p3q1r9s7t5u3v1w9y7
      required:
        - name
      additionalProperties: false
    UpdateTransactionalRequest:
      type: object
      minProperties: 1
      description: At least one field must be provided.
      properties:
        name:
          type: string
          examples:
            - Password reset email
        transactionalGroupId:
          type: string
          description: The ID of the group to move this transactional email to.
          examples:
            - clg7n5p3q1r9s7t5u3v1w9y7
      additionalProperties: false
    ContactProperty:
      type: object
      properties:
        key:
          type: string
          description: The key of the contact property.
        label:
          type: string
          description: The human-friendly label for this property.
        type:
          type: string
          description: The type of property.
          enum:
            - string
            - number
            - boolean
            - date
      examples:
        - key: favoriteColor
          label: Favorite color
          type: string
      required:
        - key
        - label
        - type
    MailingList:
      type: object
      properties:
        id:
          type: string
          description: The ID of the mailing list.
          examples:
            - clm2k8j4h6g0f8d6s4a2b0z8
        name:
          type: string
          description: The name of the mailing list.
          examples:
            - Product updates
        description:
          type:
            - string
            - "null"
          description: The description of the mailing list. `null` if no description is set.
          examples:
            - Monthly product news and release notes
        isPublic:
          type: boolean
          description: Whether the mailing list is public (`true`) or private (`false`).
          examples:
            - true
      examples:
        - id: clm2k8j4h6g0f8d6s4a2b0z8
          name: Product updates
          description: Monthly product news and release notes
          isPublic: true
        - id: clm2k8j4h6g0f8d6s4a2b0z8
          name: Product updates
          description: null
          isPublic: true
      required:
        - id
        - name
        - description
        - isPublic
    MailingListSubscriptions:
      type: object
      description: >-
        Manage mailing list subscriptions.


        Include key-value pairs of mailing list IDs and a `boolean` denoting if
        the contact should be added (`true`) or removed (`false`) from the list.
      examples:
        - cm06f5v0e45nf0ml5754o9cix: true
          cm16k73gq014h0mmj5b6jdi9r: false
    Theme:
      type: object
      properties:
        id:
          type: string
          description: The ID of the theme.
          examples:
            - clt3u5v7w9x1y3z5a7b9c1d3
        name:
          type: string
          description: The name of the theme.
          examples:
            - Default
        styles:
          $ref: "#/components/schemas/ThemeStyles"
        isDefault:
          type: boolean
          description: Whether this theme is the team's default.
          examples:
            - true
        createdAt:
          type: string
          description: ISO 8601 timestamp for when the theme was created.
          examples:
            - 2025-06-29T07:47:39.370Z
        updatedAt:
          type: string
          description: ISO 8601 timestamp for when the theme was last updated.
          examples:
            - 2025-06-29T07:47:39.370Z
      required:
        - id
        - name
        - styles
        - isDefault
        - createdAt
        - updatedAt
      examples:
        - id: clt3u5v7w9x1y3z5a7b9c1d3
          name: Default
          styles:
            backgroundColor: "#f5f5f5"
            backgroundXPadding: 24
            backgroundYPadding: 24
            bodyColor: "#ffffff"
            bodyXPadding: 24
            bodyYPadding: 24
            bodyFontFamily: Helvetica
            bodyFontCategory: sans-serif
            borderColor: "#e5e5e5"
            borderWidth: 1
            borderRadius: 8
            buttonBodyColor: "#111827"
            buttonBodyXPadding: 16
            buttonBodyYPadding: 12
            buttonBorderColor: "#111827"
            buttonBorderWidth: 0
            buttonBorderRadius: 6
            buttonTextColor: "#ffffff"
            buttonTextFormat: 0
            buttonTextFontSize: 16
            dividerColor: "#e5e5e5"
            dividerBorderWidth: 1
            textBaseColor: "#374151"
            textBaseFontSize: 16
            textBaseLineHeight: 24
            textBaseLetterSpacing: 0
            textLinkColor: "#2563eb"
            heading1Color: "#111827"
            heading1FontSize: 28
            heading1LineHeight: 36
            heading1LetterSpacing: -0.5
            heading2Color: "#111827"
            heading2FontSize: 22
            heading2LineHeight: 30
            heading2LetterSpacing: -0.25
            heading3Color: "#111827"
            heading3FontSize: 18
            heading3LineHeight: 26
            heading3LetterSpacing: 0
          isDefault: true
          createdAt: 2025-06-29T07:47:39.370Z
          updatedAt: 2025-06-29T07:47:39.370Z
    ThemeStyles:
      type: object
      description: Flat map of style attributes, matching the attribute names accepted
        by the LMX `<Style />` tag.
      properties:
        backgroundColor:
          type: string
        backgroundXPadding:
          type: number
        backgroundYPadding:
          type: number
        bodyColor:
          type: string
        bodyXPadding:
          type: number
        bodyYPadding:
          type: number
        bodyFontFamily:
          type: string
        bodyFontCategory:
          type: string
        borderColor:
          type: string
        borderWidth:
          type: number
        borderRadius:
          type: number
        buttonBodyColor:
          type: string
        buttonBodyXPadding:
          type: number
        buttonBodyYPadding:
          type: number
        buttonBorderColor:
          type: string
        buttonBorderWidth:
          type: number
        buttonBorderRadius:
          type: number
        buttonTextColor:
          type: string
        buttonTextFormat:
          type: number
        buttonTextFontSize:
          type: number
        dividerColor:
          type: string
        dividerBorderWidth:
          type: number
        textBaseColor:
          type: string
        textBaseFontSize:
          type: number
        textBaseLineHeight:
          type: number
        textBaseLetterSpacing:
          type: number
        textLinkColor:
          type: string
        heading1Color:
          type: string
        heading1FontSize:
          type: number
        heading1LineHeight:
          type: number
        heading1LetterSpacing:
          type: number
        heading2Color:
          type: string
        heading2FontSize:
          type: number
        heading2LineHeight:
          type: number
        heading2LetterSpacing:
          type: number
        heading3Color:
          type: string
        heading3FontSize:
          type: number
        heading3LineHeight:
          type: number
        heading3LetterSpacing:
          type: number
    ListThemesResponse:
      type: object
      properties:
        pagination:
          $ref: "#/components/schemas/Pagination"
        data:
          type: array
          items:
            $ref: "#/components/schemas/Theme"
      required:
        - pagination
        - data
      examples:
        - pagination:
            totalResults: 2
            returnedResults: 2
            perPage: 20
            totalPages: 1
            nextCursor: null
            nextPage: null
          data:
            - id: clt3u5v7w9x1y3z5a7b9c1d3
              name: Default
              styles:
                backgroundColor: "#f5f5f5"
                backgroundXPadding: 24
                backgroundYPadding: 24
                bodyColor: "#ffffff"
                bodyXPadding: 24
                bodyYPadding: 24
                bodyFontFamily: Helvetica
                bodyFontCategory: sans-serif
                borderColor: "#e5e5e5"
                borderWidth: 1
                borderRadius: 8
                buttonBodyColor: "#111827"
                buttonBodyXPadding: 16
                buttonBodyYPadding: 12
                buttonBorderColor: "#111827"
                buttonBorderWidth: 0
                buttonBorderRadius: 6
                buttonTextColor: "#ffffff"
                buttonTextFormat: 0
                buttonTextFontSize: 16
                dividerColor: "#e5e5e5"
                dividerBorderWidth: 1
                textBaseColor: "#374151"
                textBaseFontSize: 16
                textBaseLineHeight: 24
                textBaseLetterSpacing: 0
                textLinkColor: "#2563eb"
                heading1Color: "#111827"
                heading1FontSize: 28
                heading1LineHeight: 36
                heading1LetterSpacing: -0.5
                heading2Color: "#111827"
                heading2FontSize: 22
                heading2LineHeight: 30
                heading2LetterSpacing: -0.25
                heading3Color: "#111827"
                heading3FontSize: 18
                heading3LineHeight: 26
                heading3LetterSpacing: 0
              isDefault: true
              createdAt: 2025-06-29T07:47:39.370Z
              updatedAt: 2025-06-29T07:47:39.370Z
    ThemeResponse:
      type: object
      properties:
        id:
          type: string
          examples:
            - clt3u5v7w9x1y3z5a7b9c1d3
          description: The ID of the theme.
        name:
          type: string
          examples:
            - Default
          description: The name of the theme.
        styles:
          $ref: "#/components/schemas/ThemeStyles"
        isDefault:
          type: boolean
          description: Whether this theme is the team's default.
          examples:
            - true
        createdAt:
          type: string
          description: ISO 8601 timestamp for when the theme was created.
          examples:
            - 2025-06-29T07:47:39.370Z
        updatedAt:
          type: string
          description: ISO 8601 timestamp for when the theme was last updated.
          examples:
            - 2025-06-29T07:47:39.370Z
      required:
        - id
        - name
        - styles
        - isDefault
        - createdAt
        - updatedAt
      examples:
        - id: clt3u5v7w9x1y3z5a7b9c1d3
          name: Default
          styles:
            backgroundColor: "#f5f5f5"
            backgroundXPadding: 24
            backgroundYPadding: 24
            bodyColor: "#ffffff"
            bodyXPadding: 24
            bodyYPadding: 24
            bodyFontFamily: Helvetica
            bodyFontCategory: sans-serif
            borderColor: "#e5e5e5"
            borderWidth: 1
            borderRadius: 8
            buttonBodyColor: "#111827"
            buttonBodyXPadding: 16
            buttonBodyYPadding: 12
            buttonBorderColor: "#111827"
            buttonBorderWidth: 0
            buttonBorderRadius: 6
            buttonTextColor: "#ffffff"
            buttonTextFormat: 0
            buttonTextFontSize: 16
            dividerColor: "#e5e5e5"
            dividerBorderWidth: 1
            textBaseColor: "#374151"
            textBaseFontSize: 16
            textBaseLineHeight: 24
            textBaseLetterSpacing: 0
            textLinkColor: "#2563eb"
            heading1Color: "#111827"
            heading1FontSize: 28
            heading1LineHeight: 36
            heading1LetterSpacing: -0.5
            heading2Color: "#111827"
            heading2FontSize: 22
            heading2LineHeight: 30
            heading2LetterSpacing: -0.25
            heading3Color: "#111827"
            heading3FontSize: 18
            heading3LineHeight: 26
            heading3LetterSpacing: 0
          isDefault: true
          createdAt: 2025-06-29T07:47:39.370Z
          updatedAt: 2025-06-29T07:47:39.370Z
    ThemeFailureResponse:
      type: object
      properties:
        message:
          type: string
      required:
        - message
      examples:
        - message: Theme not found.
    CreateThemeBody:
      type: object
      properties:
        name:
          type: string
          description: The theme name.
          examples:
            - Dark mode
        styles:
          description: Style attributes for the theme. Attributes use the same names as
            the LMX [`<Style />`](/creating-emails/lmx#document-styles) tag
            attributes.
          $ref: "#/components/schemas/ThemeStyles"
      required:
        - name
      examples:
        - name: Dark mode
          styles:
            backgroundColor: "#111827"
            bodyColor: "#1f2937"
    UpdateThemeBody:
      type: object
      description: At least one of `name` or `styles` must be provided.
      properties:
        name:
          type: string
        styles:
          $ref: "#/components/schemas/ThemeStyles"
    UpdateThemeResponse:
      allOf:
        - $ref: "#/components/schemas/ThemeResponse"
        - type: object
          properties:
            affectedEmailCount:
              type: number
              description: The number of emails using this theme that are affected by the
                style change. `0` when only the name changed.
          required:
            - affectedEmailCount
      examples:
        - id: clt3u5v7w9x1y3z5a7b9c1d3
          name: Default
          styles:
            backgroundColor: "#f5f5f5"
            backgroundXPadding: 24
            backgroundYPadding: 24
            bodyColor: "#ffffff"
            bodyXPadding: 24
            bodyYPadding: 24
            bodyFontFamily: Helvetica
            bodyFontCategory: sans-serif
            borderColor: "#e5e5e5"
            borderWidth: 1
            borderRadius: 8
            buttonBodyColor: "#111827"
            buttonBodyXPadding: 16
            buttonBodyYPadding: 12
            buttonBorderColor: "#111827"
            buttonBorderWidth: 0
            buttonBorderRadius: 6
            buttonTextColor: "#ffffff"
            buttonTextFormat: 0
            buttonTextFontSize: 16
            dividerColor: "#e5e5e5"
            dividerBorderWidth: 1
            textBaseColor: "#374151"
            textBaseFontSize: 16
            textBaseLineHeight: 24
            textBaseLetterSpacing: 0
            textLinkColor: "#2563eb"
            heading1Color: "#111827"
            heading1FontSize: 28
            heading1LineHeight: 36
            heading1LetterSpacing: -0.5
            heading2Color: "#111827"
            heading2FontSize: 22
            heading2LineHeight: 30
            heading2LetterSpacing: -0.25
            heading3Color: "#111827"
            heading3FontSize: 18
            heading3LineHeight: 26
            heading3LetterSpacing: 0
          isDefault: true
          createdAt: 2025-06-29T07:47:39.370Z
          updatedAt: 2025-06-29T07:47:39.370Z
          affectedEmailCount: 12
    Component:
      type: object
      properties:
        id:
          type: string
          examples:
            - clp2o4i6u8y0t5r3e1w7q9s1
        name:
          type: string
          examples:
            - Header
        lmx:
          type: string
          description: The component body serialized as LMX.
          examples:
            - <Paragraph>Welcome to Acme</Paragraph>
      required:
        - id
        - name
        - lmx
      examples:
        - id: clp2o4i6u8y0t5r3e1w7q9s1
          name: Header
          lmx: <Paragraph>Welcome to Acme</Paragraph>
    ListComponentsResponse:
      type: object
      properties:
        pagination:
          $ref: "#/components/schemas/Pagination"
        data:
          type: array
          items:
            $ref: "#/components/schemas/Component"
      required:
        - pagination
        - data
      examples:
        - pagination:
            totalResults: 2
            returnedResults: 2
            perPage: 20
            totalPages: 1
            nextCursor: null
            nextPage: null
          data:
            - id: clp2o4i6u8y0t5r3e1w7q9s1
              name: Header
              lmx: <Paragraph>Welcome to Acme</Paragraph>
    ComponentResponse:
      type: object
      properties:
        id:
          type: string
          description: The ID of the component.
        name:
          type: string
          description: The name of the component.
        lmx:
          type: string
          description: The component body serialized as LMX.
      required:
        - id
        - name
        - lmx
      examples:
        - id: clp2o4i6u8y0t5r3e1w7q9s1
          name: Header
          lmx: <Paragraph>Welcome to Acme</Paragraph>
    ComponentFailureResponse:
      type: object
      properties:
        message:
          type: string
      required:
        - message
      examples:
        - message: Component not found.
    ComponentValidationFailureResponse:
      type: object
      properties:
        message:
          type: string
        invalidTags:
          type: array
          description: The dynamic variables that the change would push into an email that
            cannot use them. Present only when the update was rejected for that
            reason.
          items:
            type: string
      required:
        - message
      examples:
        - message: Component uses unsupported contact properties.
          invalidTags:
            - companyName
    CreateComponentBody:
      type: object
      properties:
        name:
          type: string
          description: The component name.
        lmx:
          type: string
          description: The component body as an LMX string.
      required:
        - name
        - lmx
      examples:
        - name: Header
          lmx: <Paragraph>Welcome to Acme</Paragraph>
    UpdateComponentBody:
      type: object
      description: At least one of `name` or `lmx` must be provided.
      properties:
        name:
          type: string
        lmx:
          type: string
          description: The component body as an LMX string.
    UpdateComponentResponse:
      allOf:
        - $ref: "#/components/schemas/ComponentResponse"
        - type: object
          properties:
            affectedEmailCount:
              type: number
              description: The number of emails using this component that were updated by the
                body change. `0` when only the name changed.
          required:
            - affectedEmailCount
      examples:
        - id: clp2o4i6u8y0t5r3e1w7q9s1
          name: Header
          lmx: <Paragraph>Welcome to Acme</Paragraph>
          affectedEmailCount: 3
    AudienceSegment:
      type: object
      properties:
        id:
          type: string
          description: The ID of the audience segment.
          examples:
            - cls6e8g0i2k4m6o8q0s2u4w6
        name:
          type: string
          description: The name of the audience segment.
          examples:
            - Power users
        description:
          type:
            - string
            - "null"
          description: An optional description of the audience segment.
          examples:
            - Contacts on the pro plan
        createdAt:
          type: string
          description: ISO 8601 timestamp for when the audience segment was created.
          examples:
            - 2025-06-29T07:47:39.370Z
        updatedAt:
          type: string
          description: ISO 8601 timestamp for when the audience segment was last updated.
          examples:
            - 2025-06-29T07:47:39.370Z
        filter:
          $ref: "#/components/schemas/AudienceFilter"
      required:
        - id
        - name
        - description
        - createdAt
        - updatedAt
        - filter
      examples:
        - id: cls6e8g0i2k4m6o8q0s2u4w6
          name: Power users
          description: Contacts on the pro plan
          createdAt: 2025-06-29T07:47:39.370Z
          updatedAt: 2025-06-29T07:47:39.370Z
          filter:
            match: all
            conditions:
              - type: property
                key: plan
                operator: equals
                value: pro
    ListAudienceSegmentsResponse:
      type: object
      properties:
        pagination:
          $ref: "#/components/schemas/Pagination"
        data:
          type: array
          items:
            $ref: "#/components/schemas/AudienceSegment"
      required:
        - pagination
        - data
      examples:
        - pagination:
            totalResults: 2
            returnedResults: 2
            perPage: 20
            totalPages: 1
            nextCursor: null
            nextPage: null
          data:
            - id: cls6e8g0i2k4m6o8q0s2u4w6
              name: Power users
              description: Contacts on the pro plan
              createdAt: 2025-06-29T07:47:39.370Z
              updatedAt: 2025-06-29T07:47:39.370Z
              filter:
                match: all
                conditions:
                  - type: property
                    key: plan
                    operator: equals
                    value: pro
    AudienceSegmentResponse:
      $ref: "#/components/schemas/AudienceSegment"
      examples:
        - id: cls6e8g0i2k4m6o8q0s2u4w6
          name: Power users
          description: Contacts on the pro plan
          createdAt: 2025-06-29T07:47:39.370Z
          updatedAt: 2025-06-29T07:47:39.370Z
          filter:
            match: all
            conditions:
              - type: property
                key: plan
                operator: equals
                value: pro
    CreateAudienceSegmentRequest:
      type: object
      properties:
        name:
          type: string
          maxLength: 255
          description: The name of the audience segment. Must be unique within the team.
          examples:
            - Active users
        description:
          type: string
          maxLength: 1000
          description: An optional description of the audience segment.
        filter:
          type: object
          description: A tree of audience conditions combined with `match`.
          properties:
            match:
              type: string
              enum:
                - all
                - any
            conditions:
              type: array
              minItems: 1
              items:
                $ref: "#/components/schemas/AudienceFilterCondition"
          required:
            - match
            - conditions
          additionalProperties: false
      required:
        - name
        - filter
      additionalProperties: false
    AudienceSegmentFailureResponse:
      type: object
      properties:
        message:
          type: string
      required:
        - message
      examples:
        - message: Audience segment not found.
    CampaignScheduling:
      type: object
      description: When the campaign is scheduled to send.
      properties:
        method:
          type: string
          enum:
            - now
            - schedule
        timestamp:
          type:
            - string
            - "null"
          format: date-time
          description: ISO 8601 send time. Null when the method is `now`.
      required:
        - method
        - timestamp
      examples:
        - method: schedule
          timestamp: 2025-07-15T14:00:00.000Z
    CampaignSchedulingRequest:
      type: object
      description: When the campaign should send. `timestamp` is required and must be
        in the future when `method` is `schedule`, and must be omitted when
        `method` is `now`.
      properties:
        method:
          type: string
          enum:
            - now
            - schedule
        timestamp:
          type: string
          format: date-time
      required:
        - method
      additionalProperties: false
      examples:
        - method: schedule
          timestamp: 2025-07-15T14:00:00.000Z
    AudienceFilter:
      type:
        - object
        - "null"
      description: A tree of audience conditions combined with `match`.
      properties:
        match:
          type: string
          enum:
            - all
            - any
        conditions:
          type: array
          minItems: 1
          items:
            $ref: "#/components/schemas/AudienceFilterCondition"
      required:
        - match
        - conditions
      additionalProperties: false
    AudienceFilterInRequest:
      type:
        - object
        - "null"
      description: A tree of audience conditions combined with `match`. Setting this
        without also providing `audienceSegmentId` clears any existing
        `audienceSegmentId`. When both are provided, this filter is applied on
        top of the segment's filter.
      properties:
        match:
          type: string
          enum:
            - all
            - any
        conditions:
          type: array
          minItems: 1
          items:
            $ref: "#/components/schemas/AudienceFilterCondition"
      required:
        - match
        - conditions
      additionalProperties: false
    AudienceFilterCondition:
      oneOf:
        - $ref: "#/components/schemas/PropertyCondition"
        - $ref: "#/components/schemas/OptInCondition"
        - $ref: "#/components/schemas/ActivityCondition"
      discriminator:
        propertyName: type
    PropertyCondition:
      type: object
      description: Matches contacts by a property value.
      properties:
        type:
          type: string
          enum:
            - property
        key:
          type: string
          description: The contact property name.
        operator:
          type: string
          enum:
            - any
            - contains
            - notContains
            - equals
            - notEquals
            - greaterThan
            - lessThan
            - isTrue
            - isFalse
            - empty
            - notEmpty
            - dateEmpty
            - dateNotEmpty
            - after
            - before
            - between
        value:
          description: The comparison value. Omitted for value-less operators (e.g.
            `isTrue`, `empty`). A `{ from, to }` object for `between`.
          oneOf:
            - type: string
            - type: number
            - type: object
              properties:
                from:
                  type: string
                  format: date-time
                to:
                  type: string
                  format: date-time
              required:
                - from
                - to
      required:
        - type
        - key
        - operator
      examples:
        - type: property
          key: plan
          operator: equals
          value: pro
    OptInCondition:
      type: object
      description: Matches contacts by mailing-list opt-in status.
      properties:
        type:
          type: string
          enum:
            - optIn
        status:
          type:
            - string
            - "null"
          enum:
            - accepted
            - pending
            - rejected
            - null
      required:
        - type
        - status
      examples:
        - type: optIn
          status: accepted
    ActivityCondition:
      type: object
      description: Matches contacts by their activity on a campaign or workflow.
      properties:
        type:
          type: string
          enum:
            - activity
        action:
          type: string
          enum:
            - sent
            - opened
            - clicked
        negate:
          type: boolean
        target:
          type: string
          enum:
            - campaign
            - workflow
            - workflowEmail
        id:
          type: string
          description: The ID of the campaign, workflow, or workflow email.
      required:
        - type
        - action
        - negate
        - target
        - id
      examples:
        - type: activity
          action: opened
          negate: false
          target: campaign
          id: clc4m6n8p0q2r4s6t8u0v2x4
    CampaignListItem:
      $ref: "#/components/schemas/CampaignResponse"
    ListCampaignsResponse:
      type: object
      properties:
        pagination:
          $ref: "#/components/schemas/Pagination"
        data:
          type: array
          items:
            $ref: "#/components/schemas/CampaignResponse"
      required:
        - pagination
        - data
      examples:
        - pagination:
            totalResults: 45
            returnedResults: 20
            perPage: 20
            totalPages: 3
            nextCursor: clp9k2m4n6p8q0r2s4t6u8v0
            nextPage: https://app.loops.so/api/v1/campaigns?cursor=clp9k2m4n6p8q0r2s4t6u8v0&perPage=20
          data:
            - id: clc4m6n8p0q2r4s6t8u0v2x4
              url: https://app.loops.so/campaigns/clc4m6n8p0q2r4s6t8u0v2x4
              name: Spring announcement
              status: Draft
              createdAt: 2025-06-29T07:47:39.370Z
              updatedAt: 2025-06-29T07:47:39.370Z
              emailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
              campaignGroupId: clg7n5p3q1r9s7t5u3v1w9y7
              mailingListId: clm2k8j4h6g0f8d6s4a2b0z8
              audienceSegmentId: null
              audienceFilter: null
              scheduling:
                method: now
                timestamp: null
    CreateCampaignRequest:
      type: object
      properties:
        name:
          type: string
          description: The campaign name.
          examples:
            - Spring announcement
        campaignGroupId:
          type: string
          description: The ID of the group to add this campaign to. Defaults to the team's
            default group when omitted.
          examples:
            - clg7n5p3q1r9s7t5u3v1w9y7
        mailingListId:
          type:
            - string
            - "null"
          description: The ID of the mailing list to send to.
          examples:
            - clm2k8j4h6g0f8d6s4a2b0z8
        audienceSegmentId:
          type:
            - string
            - "null"
          description: The ID of an audience segment. Setting this without also providing
            `audienceFilter` clears any existing `audienceFilter`. If both are
            provided, the filter is applied on top of the segment's filter.
          examples:
            - cls6e8g0i2k4m6o8q0s2u4w6
        audienceFilter:
          $ref: "#/components/schemas/AudienceFilterInRequest"
        scheduling:
          $ref: "#/components/schemas/CampaignSchedulingRequest"
      required:
        - name
      additionalProperties: false
    CreateCampaignResponse:
      type: object
      properties:
        id:
          type: string
          description: The ID of the campaign.
          examples:
            - clc4m6n8p0q2r4s6t8u0v2x4
        url:
          type: string
          format: uri
          description: The URL of the campaign in the Loops app.
          examples:
            - https://app.loops.so/campaigns/clc4m6n8p0q2r4s6t8u0v2x4
        name:
          type: string
          description: The name of the campaign.
          examples:
            - Spring announcement
        status:
          type: string
          examples:
            - Draft
          enum:
            - Draft
          description: The status of the campaign (always `Draft` for new campaigns).
        createdAt:
          type: string
          format: date-time
          examples:
            - 2025-06-29T07:47:39.370Z
          description: ISO 8601 timestamp for when the campaign was created.
        updatedAt:
          type: string
          format: date-time
          examples:
            - 2025-06-29T07:47:39.370Z
          description: ISO 8601 timestamp for when the campaign was last updated.
        emailMessageId:
          type:
            - string
            - "null"
          description: The ID of the empty email message created for this campaign. Use
            `POST /v1/email-messages/{emailMessageId}` to set its fields and LMX
            content.
          examples:
            - cle5f7g9h1i3j5k7l9m1n3p5
        emailMessageContentRevisionId:
          type:
            - string
            - "null"
          description: The `contentRevisionId` of the newly created email message. Pass
            this as `expectedRevisionId` on your first update.
          examples:
            - clrev1s10n2i3d4e5f6g7h8
        campaignGroupId:
          type:
            - string
            - "null"
          description: The ID of the campaign group this campaign belongs to, if set.
          examples:
            - clg7n5p3q1r9s7t5u3v1w9y7
        mailingListId:
          type:
            - string
            - "null"
          description: The ID of the mailing list this campaign sends to, if set.
          examples:
            - clm2k8j4h6g0f8d6s4a2b0z8
        audienceSegmentId:
          type:
            - string
            - "null"
          description: The ID of the audience segment this campaign targets, if set.
          examples:
            - cls6e8g0i2k4m6o8q0s2u4w6
        audienceFilter:
          $ref: "#/components/schemas/AudienceFilter"
          description: The filter rules that define the audience for this campaign, if set.
        scheduling:
          $ref: "#/components/schemas/CampaignScheduling"
          description: When the campaign is scheduled to send.
      required:
        - id
        - url
        - name
        - status
        - createdAt
        - updatedAt
        - emailMessageId
        - emailMessageContentRevisionId
        - campaignGroupId
        - mailingListId
        - audienceSegmentId
        - audienceFilter
        - scheduling
      examples:
        - id: clc4m6n8p0q2r4s6t8u0v2x4
          url: https://app.loops.so/campaigns/clc4m6n8p0q2r4s6t8u0v2x4
          name: Spring announcement
          status: Draft
          createdAt: 2025-06-29T07:47:39.370Z
          updatedAt: 2025-06-29T07:47:39.370Z
          emailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
          campaignGroupId: clg7n5p3q1r9s7t5u3v1w9y7
          mailingListId: clm2k8j4h6g0f8d6s4a2b0z8
          audienceSegmentId: null
          audienceFilter: null
          scheduling:
            method: now
            timestamp: null
          emailMessageContentRevisionId: clrev1s10n2i3d4e5f6g7h8
    UpdateCampaignRequest:
      type: object
      description: At least one field must be provided.
      properties:
        name:
          type: string
          description: The updated campaign name.
          examples:
            - Spring announcement
        campaignGroupId:
          type: string
          description: The ID of the group to move this campaign to.
          examples:
            - clg7n5p3q1r9s7t5u3v1w9y7
        mailingListId:
          type:
            - string
            - "null"
          description: The ID of the mailing list to send to.
          examples:
            - clm2k8j4h6g0f8d6s4a2b0z8
        audienceSegmentId:
          type:
            - string
            - "null"
          description: The ID of an audience segment. Setting this without also providing
            `audienceFilter` clears any existing `audienceFilter`. If both are
            provided, the filter is applied on top of the segment's filter.
          examples:
            - cls6e8g0i2k4m6o8q0s2u4w6
        audienceFilter:
          $ref: "#/components/schemas/AudienceFilterInRequest"
        scheduling:
          $ref: "#/components/schemas/CampaignSchedulingRequest"
      additionalProperties: false
    CampaignResponse:
      type: object
      properties:
        id:
          type: string
          description: The ID of the campaign.
          examples:
            - clc4m6n8p0q2r4s6t8u0v2x4
        url:
          type: string
          format: uri
          description: The URL of the campaign in the Loops app.
          examples:
            - https://app.loops.so/campaigns/clc4m6n8p0q2r4s6t8u0v2x4
        name:
          type: string
          description: The name of the campaign.
          examples:
            - Spring announcement
        status:
          type: string
          description: The status of the campaign.
          enum:
            - Draft
            - Scheduled
            - Sending
            - Sent
          examples:
            - Draft
        createdAt:
          type: string
          format: date-time
          examples:
            - 2025-06-29T07:47:39.370Z
          description: ISO 8601 timestamp for when the campaign was created.
        updatedAt:
          type: string
          format: date-time
          examples:
            - 2025-06-29T07:47:39.370Z
          description: ISO 8601 timestamp for when the campaign was last updated.
        emailMessageId:
          type:
            - string
            - "null"
          description: The associated email message ID.
          examples:
            - cle5f7g9h1i3j5k7l9m1n3p5
        campaignGroupId:
          type:
            - string
            - "null"
          description: The ID of the campaign group this campaign belongs to.
          examples:
            - clg7n5p3q1r9s7t5u3v1w9y7
        mailingListId:
          type:
            - string
            - "null"
          examples:
            - clm2k8j4h6g0f8d6s4a2b0z8
          description: The ID of the mailing list this campaign sends to, if set.
        audienceSegmentId:
          type:
            - string
            - "null"
          description: The ID of the audience segment this campaign targets, if set.
          examples:
            - cls6e8g0i2k4m6o8q0s2u4w6
        audienceFilter:
          $ref: "#/components/schemas/AudienceFilter"
          description: The filter rules that define the audience for this campaign, if set.
        scheduling:
          $ref: "#/components/schemas/CampaignScheduling"
      required:
        - id
        - url
        - name
        - status
        - createdAt
        - updatedAt
        - emailMessageId
        - campaignGroupId
        - mailingListId
        - audienceSegmentId
        - audienceFilter
        - scheduling
      examples:
        - id: clc4m6n8p0q2r4s6t8u0v2x4
          url: https://app.loops.so/campaigns/clc4m6n8p0q2r4s6t8u0v2x4
          name: Spring announcement
          status: Draft
          createdAt: 2025-06-29T07:47:39.370Z
          updatedAt: 2025-06-29T07:47:39.370Z
          emailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
          campaignGroupId: clg7n5p3q1r9s7t5u3v1w9y7
          mailingListId: clm2k8j4h6g0f8d6s4a2b0z8
          audienceSegmentId: null
          audienceFilter: null
          scheduling:
            method: now
            timestamp: null
    CampaignFailureResponse:
      type: object
      properties:
        message:
          type: string
      required:
        - message
      examples:
        - message: Campaign not found.
    WorkflowSummary:
      type: object
      properties:
        id:
          type: string
          description: The ID of the workflow.
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
        url:
          type: string
          format: uri
          description: The URL of the workflow in the Loops app.
          examples:
            - https://app.loops.so/workflows/clw1a3b5c7d9e1f3g5h7i9j1
        name:
          type: string
          description: The name of the workflow.
          examples:
            - Welcome series
        createdAt:
          type: string
          format: date-time
          examples:
            - 2025-06-29T07:47:39.370Z
          description: ISO 8601 timestamp for when the workflow was created.
        updatedAt:
          type: string
          format: date-time
          examples:
            - 2025-06-29T07:47:39.370Z
          description: ISO 8601 timestamp for when the workflow was last updated.
      required:
        - id
        - url
        - name
        - createdAt
        - updatedAt
      examples:
        - id: clw1a3b5c7d9e1f3g5h7i9j1
          url: https://app.loops.so/workflows/clw1a3b5c7d9e1f3g5h7i9j1
          name: Welcome series
          createdAt: 2025-06-29T07:47:39.370Z
          updatedAt: 2025-06-29T07:47:39.370Z
    ListWorkflowsResponse:
      type: object
      properties:
        pagination:
          $ref: "#/components/schemas/Pagination"
        data:
          type: array
          items:
            $ref: "#/components/schemas/WorkflowSummary"
      required:
        - pagination
        - data
      examples:
        - pagination:
            totalResults: 45
            returnedResults: 20
            perPage: 20
            totalPages: 3
            nextCursor: clp9k2m4n6p8q0r2s4t6u8v0
            nextPage: https://app.loops.so/api/v1/workflows?cursor=clp9k2m4n6p8q0r2s4t6u8v0&perPage=20
          data:
            - id: clw1a3b5c7d9e1f3g5h7i9j1
              url: https://app.loops.so/workflows/clw1a3b5c7d9e1f3g5h7i9j1
              name: Welcome series
              createdAt: 2025-06-29T07:47:39.370Z
              updatedAt: 2025-06-29T07:47:39.370Z
    WorkflowRevisionId:
      type:
        - string
      description: The current workflow revision token. Pass the latest value as
        `expectedRevisionId` on the next workflow mutation.
    NullableWorkflowRevisionId:
      type:
        - string
        - "null"
      description: The current workflow revision token. Pass the latest value as
        `expectedRevisionId` on the next workflow mutation. Will be `null` for
        workflows without a revision token yet.
    WorkflowReEligible:
      type: boolean
      description: If `true`, the contacts will be able to enter this workflow every
        time the trigger is matched. If `false`, contacts will only ever enter
        this workflow once. Matches the "Trigger frequency" option in the UI.
    WorkflowNextNodeIds:
      type: array
      items:
        type: string
      description: The IDs of the nodes that are downstream of this node.
    WorkflowExpectedRevisionId:
      type:
        - string
        - "null"
      description: The workflow revision token returned by the latest workflow read or
        mutation. Older workflows may return `null` before their first
        revision-aware mutation; pass `null` back as `expectedRevisionId` in
        that case. If the token is stale, the API returns a `409 Conflict`
        error.
    WorkflowQueuedContactPolicy:
      type: string
      enum:
        - fail
        - discard
      default: fail
      description: "`fail` returns queued-contact impact instead of mutating.
        `discard` confirms that matching queued contacts should be discarded.
        Defaults to `fail` when omitted."
    SimplifiedWorkflow:
      type: object
      properties:
        id:
          type: string
          description: The ID of the workflow.
        url:
          type: string
          format: uri
          description: The URL of the workflow in the Loops app.
          examples:
            - https://app.loops.so/workflows/clw1a3b5c7d9e1f3g5h7i9j1
        workflowRevisionId:
          $ref: "#/components/schemas/NullableWorkflowRevisionId"
        status:
          type: string
          enum:
            - Draft
            - Sending
            - Paused
            - PausedAndQueueing
        name:
          type: string
          description: The name of the workflow.
        description:
          type: string
          description: The description of the workflow.
        mailingListId:
          type:
            - string
            - "null"
          description: The ID of the mailing list the workflow sends to.
        rootNodeId:
          type: string
          description: The ID of the root node in the workflow graph.
        nodes:
          type: object
          description: A map of node IDs to simplified node objects. Each node includes
            `typeName` and `nextNodeIds`, plus type-specific fields when
            present. To get the full node object, use the `GET
            /v1/workflows/{workflowId}/nodes/{nodeId}` endpoint.
          additionalProperties:
            $ref: "#/components/schemas/SimplifiedWorkflowNode"
          example:
            cf16k73gq014h3mmj5b6jdi9r:
              typeName: SignupTrigger
              nextNodeIds:
                - cf16k73gq014h3mmj5b4jdifg
                - cf16k73gq014h3mmj5b4jdifh
      required:
        - id
        - url
        - workflowRevisionId
        - status
        - mailingListId
        - rootNodeId
        - nodes
      examples:
        - id: clw1a3b5c7d9e1f3g5h7i9j1
          url: https://app.loops.so/workflows/clw1a3b5c7d9e1f3g5h7i9j1
          status: Draft
          name: Welcome series
          description: Onboarding emails for new signups
          mailingListId: clm2k8j4h6g0f8d6s4a2b0z8
          rootNodeId: cln8p0q2r4s6t8u0v2w4x6z8
          nodes:
            cln8p0q2r4s6t8u0v2w4x6z8:
              typeName: SignupTrigger
              nextNodeIds:
                - cln1a3b5c7d9e1f3g5h7i9j1
            cln1a3b5c7d9e1f3g5h7i9j1:
              typeName: SendEmailAction
              nextNodeIds: []
              emailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
              subject: Welcome to Acme!
    CreateWorkflowRequest:
      type: object
      properties:
        name:
          type: string
          description: The name of the workflow.
        description:
          type: string
          description: The description of the workflow.
        mailingListId:
          type:
            - string
            - "null"
          description: The ID of a mailing list the workflow sends to. After creation, the
            mailing list can be changed with the
            `/v1/workflows/{workflowId}/mailing-list` endpoint.
      required:
        - name
      additionalProperties: false
    UpdateWorkflowPropertiesRequest:
      type: object
      description: At least one property must be provided.
      properties:
        expectedRevisionId:
          $ref: "#/components/schemas/WorkflowExpectedRevisionId"
        name:
          type: string
          description: The updated workflow name.
        description:
          type: string
          description: The updated workflow description.
      required:
        - expectedRevisionId
      anyOf:
        - required:
            - name
        - required:
            - description
      additionalProperties: false
    DeleteWorkflowRequest:
      type: object
      properties:
        expectedRevisionId:
          $ref: "#/components/schemas/WorkflowExpectedRevisionId"
        confirmDelete:
          type: boolean
          description: Set to `true` after a confirmation-required `409 Conflict` response
            to confirm deleting a sending workflow or a workflow with queued
            contacts.
      required:
        - expectedRevisionId
      additionalProperties: false
    WorkflowMutationNode:
      description: Detailed workflow node returned from create and update mutations.
        The exact fields depend on `typeName`.
      oneOf:
        - $ref: "#/components/schemas/SignupTriggerWorkflowMutationNode"
        - $ref: "#/components/schemas/EventTriggerWorkflowMutationNode"
        - $ref: "#/components/schemas/ContactPropertyTriggerWorkflowMutationNode"
        - $ref: "#/components/schemas/AddToListTriggerWorkflowMutationNode"
        - $ref: "#/components/schemas/BlankTriggerWorkflowMutationNode"
        - $ref: "#/components/schemas/AudienceFilterWorkflowMutationNode"
        - $ref: "#/components/schemas/TimerActionWorkflowMutationNode"
        - $ref: "#/components/schemas/SendEmailActionWorkflowMutationNode"
        - $ref: "#/components/schemas/ExitActionWorkflowMutationNode"
        - $ref: "#/components/schemas/BranchWorkflowMutationNode"
        - $ref: "#/components/schemas/ExperimentBranchWorkflowMutationNode"
        - $ref: "#/components/schemas/VariantWorkflowMutationNode"
      discriminator:
        propertyName: typeName
        mapping:
          SignupTrigger: "#/components/schemas/SignupTriggerWorkflowMutationNode"
          EventTrigger: "#/components/schemas/EventTriggerWorkflowMutationNode"
          ContactPropertyTrigger: "#/components/schemas/ContactPropertyTriggerWorkflowMutationNode"
          AddToListTrigger: "#/components/schemas/AddToListTriggerWorkflowMutationNode"
          BlankTrigger: "#/components/schemas/BlankTriggerWorkflowMutationNode"
          AudienceFilter: "#/components/schemas/AudienceFilterWorkflowMutationNode"
          TimerAction: "#/components/schemas/TimerActionWorkflowMutationNode"
          SendEmailAction: "#/components/schemas/SendEmailActionWorkflowMutationNode"
          ExitAction: "#/components/schemas/ExitActionWorkflowMutationNode"
          BranchNode: "#/components/schemas/BranchWorkflowMutationNode"
          ExperimentBranchNode: "#/components/schemas/ExperimentBranchWorkflowMutationNode"
          VariantNode: "#/components/schemas/VariantWorkflowMutationNode"
    WorkflowMutationNodeRevision:
      type: object
      properties:
        workflowRevisionId:
          $ref: "#/components/schemas/WorkflowRevisionId"
      required:
        - workflowRevisionId
    SignupTriggerWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
            - SignupTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
      required:
        - id
        - typeName
        - nextNodeIds
    EventTriggerWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
            - EventTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        eventName:
          type: string
          description: The name of the event pattern that triggers this node.
        eventProperties:
          type: array
          items:
            $ref: "#/components/schemas/WorkflowEventProperty"
          description: The properties of the event pattern, which can be used in emails.
        reEligible:
          $ref: "#/components/schemas/WorkflowReEligible"
      required:
        - id
        - typeName
        - nextNodeIds
        - reEligible
    ContactPropertyTriggerWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
            - ContactPropertyTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        contactPropertyQuery:
          oneOf:
            - $ref: "#/components/schemas/WorkflowContactPropertyQuery"
            - type: "null"
        reEligible:
          $ref: "#/components/schemas/WorkflowReEligible"
      required:
        - id
        - typeName
        - nextNodeIds
        - contactPropertyQuery
        - reEligible
    AddToListTriggerWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
            - AddToListTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        mailingListId:
          type:
            - string
            - "null"
          description: The ID of the mailing list this trigger sends to, if set.
        reEligible:
          $ref: "#/components/schemas/WorkflowReEligible"
      required:
        - id
        - typeName
        - nextNodeIds
        - mailingListId
        - reEligible
    BlankTriggerWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
            - BlankTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
      required:
        - id
        - typeName
        - nextNodeIds
    AudienceFilterWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
            - AudienceFilter
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        audienceFilter:
          $ref: "#/components/schemas/AudienceFilter"
        audienceSegmentId:
          type: string
          description: The ID of the audience segment this trigger targets.
        appliesDownstream:
          description: If `true`, the audience filter will apply to all downstream nodes.
            If `false`, the audience filter will only apply to the current node.
            Matches the "Filter scope" option in the UI.
          type: boolean
      required:
        - id
        - typeName
        - nextNodeIds
        - appliesDownstream
    TimerActionWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
            - TimerAction
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        amount:
          $ref: "#/components/schemas/WorkflowTimerAmount"
        unit:
          $ref: "#/components/schemas/WorkflowTimerUnit"
      required:
        - id
        - typeName
        - nextNodeIds
        - amount
        - unit
    SendEmailActionWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
            - SendEmailAction
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        emailMessageId:
          type: string
          description: The ID of the email message to send. To edit this email, use the
            `POST /v1/email-messages/{emailMessageId}` endpoint.
        subject:
          type: string
      required:
        - id
        - typeName
        - nextNodeIds
        - emailMessageId
        - subject
    ExitActionWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
            - ExitAction
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
      required:
        - id
        - typeName
        - nextNodeIds
    BranchWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
            - BranchNode
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
      required:
        - id
        - typeName
        - nextNodeIds
    ExperimentBranchWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
            - ExperimentBranchNode
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        samplingRate:
          type: number
          description: The percentage of contacts that will be sent to variant branches,
            between `0` and `100`. The remaining percentage will be sent to the
            control branch. `100` sends all contacts to variant branches.
      required:
        - id
        - typeName
        - nextNodeIds
        - samplingRate
    VariantWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
            - VariantNode
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        isControl:
          type: boolean
          description: Whether this is the control variant of an experiment.
      required:
        - id
        - typeName
        - nextNodeIds
    UpdateWorkflowNodePayload:
      anyOf:
        - $ref: "#/components/schemas/WorkflowSignupTriggerPayload"
        - $ref: "#/components/schemas/WorkflowEventTriggerPayload"
        - $ref: "#/components/schemas/WorkflowContactPropertyTriggerPayload"
        - $ref: "#/components/schemas/WorkflowAddToListTriggerPayload"
        - $ref: "#/components/schemas/WorkflowAudienceFilterPayload"
        - $ref: "#/components/schemas/WorkflowTimerActionPayload"
        - $ref: "#/components/schemas/WorkflowExperimentBranchPayload"
        - $ref: "#/components/schemas/WorkflowVariantPayload"
      description: Node-type-specific fields to update. The allowed fields depend on
        the existing node type. Trigger node updates may include `typeName` when
        changing one trigger node type to another trigger node type.
    WorkflowSignupTriggerPayload:
      type: object
      description: Changes an existing trigger node to a signup trigger.
      properties:
        typeName:
          type: string
          enum:
            - SignupTrigger
      required:
        - typeName
      additionalProperties: false
    WorkflowEventTriggerPayload:
      type: object
      description: Updates an event trigger, or changes an existing trigger node to an
        event trigger. Assign the event pattern with either `eventPatternId` or
        `eventName`, not both. Set either field to `null` to clear the
        event-pattern relationship.
      minProperties: 1
      properties:
        typeName:
          type: string
          enum:
            - EventTrigger
        eventPatternId:
          type:
            - string
            - "null"
          description: The ID of the event pattern to trigger on. Use either
            `eventPatternId` or `eventName`, not both. Set to `null` to clear
            the event-pattern relationship.
        eventName:
          type:
            - string
            - "null"
          description: The name of the event pattern to trigger on. Use this when you know
            the event name but not the internal event pattern ID. Use either
            `eventName` or `eventPatternId`, not both. Set to `null` to clear
            the event-pattern relationship.
        reEligible:
          $ref: "#/components/schemas/WorkflowReEligible"
      additionalProperties: false
    WorkflowContactPropertyTriggerPayload:
      type: object
      description: Updates a contact-property trigger, or changes an existing trigger
        node to a contact-property trigger.
      minProperties: 1
      properties:
        typeName:
          type: string
          enum:
            - ContactPropertyTrigger
        contactPropertyQuery:
          $ref: "#/components/schemas/WorkflowContactPropertyQuery"
        reEligible:
          $ref: "#/components/schemas/WorkflowReEligible"
      additionalProperties: false
    WorkflowAddToListTriggerPayload:
      type: object
      description: Updates an add-to-list trigger, or changes an existing trigger node
        to an add-to-list trigger.
      minProperties: 1
      properties:
        typeName:
          type: string
          enum:
            - AddToListTrigger
        reEligible:
          $ref: "#/components/schemas/WorkflowReEligible"
      additionalProperties: false
    WorkflowAudienceFilterPayload:
      type: object
      minProperties: 1
      description: Configuration for the audience filter node.
      properties:
        audienceSegmentId:
          type:
            - string
            - "null"
          description: The ID of an audience segment. Setting this without also providing
            `audienceFilter` clears any existing `audienceFilter`. If both are
            provided, the filter is applied on top of the segment's filter.
        audienceFilter:
          $ref: "#/components/schemas/AudienceFilterInRequest"
        appliesDownstream:
          type: boolean
          description: If `true`, the audience filter will apply to all downstream nodes.
            If `false`, the audience filter will only apply to the current node.
            Matches the "Filter scope" option in the UI.
      additionalProperties: false
    WorkflowTimerActionPayload:
      type: object
      minProperties: 1
      description: Configuration for the timer action node.
      properties:
        amount:
          $ref: "#/components/schemas/WorkflowTimerAmount"
        unit:
          $ref: "#/components/schemas/WorkflowTimerUnit"
      additionalProperties: false
    WorkflowExperimentBranchPayload:
      type: object
      minProperties: 1
      description: Configuration for the experiment branch node.
      properties:
        samplingRate:
          type: number
          description: The percentage of contacts that will be sent to variant branches,
            between `0` and `100`. The remaining percentage will be sent to the
            control branch. `100` sends all contacts to variant branches.
      additionalProperties: false
    WorkflowVariantPayload:
      type: object
      minProperties: 1
      description: Configuration for the variant node.
      properties:
        isControl:
          type: boolean
          description: Use `true` to set this variant as the control of the experiment.
            This will set `false` on the existing control, if one exists.
            Experiments do not require a control variant.
      additionalProperties: false
    CreateWorkflowNodeTypeName:
      type: string
      enum:
        - AudienceFilter
        - BranchNode
        - ExperimentBranchNode
        - TimerAction
        - SendEmailAction
        - VariantNode
      description: Node types that can be created with the API. `*Trigger` nodes and
        `ExitAction` nodes cannot be created.
    CreateWorkflowNodeBetweenRequest:
      type: object
      description: Insert a new node between two existing nodes, `fromNodeId` and
        `toNodeId`. When `fromNodeId` is an `ExperimentBranchNode`,
        `nodeTypeName` must be `VariantNode`, and `toNodeId` cannot already be a
        `VariantNode`; use add-branch to add sibling variants. Branch paths can
        be edited with create-node, but a workflow cannot be started unless each
        direct `BranchNode` child is an `AudienceFilter`.
      properties:
        expectedRevisionId:
          $ref: "#/components/schemas/WorkflowExpectedRevisionId"
        insertMode:
          type: string
          enum:
            - between
        nodeTypeName:
          $ref: "#/components/schemas/CreateWorkflowNodeTypeName"
        fromNodeId:
          type: string
          description: The node to insert after. This node must currently point to
            `toNodeId`. If this is an `ExperimentBranchNode`, `nodeTypeName`
            must be `VariantNode` and `toNodeId` cannot already be a
            `VariantNode`.
        toNodeId:
          type: string
          description: The node to insert before.
      required:
        - expectedRevisionId
        - insertMode
        - nodeTypeName
        - fromNodeId
        - toNodeId
      additionalProperties: false
    CreateWorkflowNodeBeforeRequest:
      type: object
      description: 'Insert a new node before `toNodeId`. `VariantNode` cannot use
        `insertMode: "before"`; to restore a missing variant path, use
        `insertMode: "between"` with the experiment branch as `fromNodeId`.'
      properties:
        expectedRevisionId:
          $ref: "#/components/schemas/WorkflowExpectedRevisionId"
        insertMode:
          type: string
          enum:
            - before
        nodeTypeName:
          $ref: "#/components/schemas/CreateWorkflowNodeTypeName"
        toNodeId:
          type: string
          description: The node to insert before. The target must have at least one
            incoming parent and cannot be a trigger node.
        beforeNodeId:
          type: string
          description: Deprecated. Use `toNodeId` instead.
          deprecated: true
      required:
        - expectedRevisionId
        - insertMode
        - nodeTypeName
      oneOf:
        - properties:
            toNodeId:
              type: string
          required:
            - toNodeId
        - properties:
            beforeNodeId:
              type: string
              deprecated: true
          required:
            - beforeNodeId
      additionalProperties: false
    CreateWorkflowNodeAfterRequest:
      type: object
      description: Insert a new node after `fromNodeId`. This is valid only when
        `fromNodeId` has exactly one outgoing node. It is invalid when
        `fromNodeId` has no outgoing nodes, multiple outgoing nodes, or is an
        exit node. When the source has multiple outgoing nodes, use `between`
        with the exact `toNodeId` instead.
      properties:
        expectedRevisionId:
          $ref: "#/components/schemas/WorkflowExpectedRevisionId"
        insertMode:
          type: string
          enum:
            - after
        nodeTypeName:
          $ref: "#/components/schemas/CreateWorkflowNodeTypeName"
        fromNodeId:
          type: string
          description: The node to insert after. This node must currently have exactly one
            outgoing node.
      required:
        - expectedRevisionId
        - insertMode
        - nodeTypeName
        - fromNodeId
      additionalProperties: false
    CreateWorkflowNodeRequest:
      oneOf:
        - $ref: "#/components/schemas/CreateWorkflowNodeBetweenRequest"
        - $ref: "#/components/schemas/CreateWorkflowNodeBeforeRequest"
        - $ref: "#/components/schemas/CreateWorkflowNodeAfterRequest"
      description: Create a new workflow node with an explicit `insertMode`. To
        configure the node after creation, use the `POST
        /v1/workflows/{workflowId}/nodes/{nodeId}` endpoint.
      discriminator:
        propertyName: insertMode
        mapping:
          between: "#/components/schemas/CreateWorkflowNodeBetweenRequest"
          before: "#/components/schemas/CreateWorkflowNodeBeforeRequest"
          after: "#/components/schemas/CreateWorkflowNodeAfterRequest"
    WorkflowMutationNodeWithRevision:
      description: Detailed workflow node returned from a mutation, plus the latest
        workflow revision token.
      oneOf:
        - $ref: "#/components/schemas/SignupTriggerWorkflowMutationNodeWithRevision"
        - $ref: "#/components/schemas/EventTriggerWorkflowMutationNodeWithRevision"
        - $ref: "#/components/schemas/ContactPropertyTriggerWorkflowMutationNodeWithRevis\
            ion"
        - $ref: "#/components/schemas/AddToListTriggerWorkflowMutationNodeWithRevision"
        - $ref: "#/components/schemas/BlankTriggerWorkflowMutationNodeWithRevision"
        - $ref: "#/components/schemas/AudienceFilterWorkflowMutationNodeWithRevision"
        - $ref: "#/components/schemas/TimerActionWorkflowMutationNodeWithRevision"
        - $ref: "#/components/schemas/SendEmailActionWorkflowMutationNodeWithRevision"
        - $ref: "#/components/schemas/ExitActionWorkflowMutationNodeWithRevision"
        - $ref: "#/components/schemas/BranchWorkflowMutationNodeWithRevision"
        - $ref: "#/components/schemas/ExperimentBranchWorkflowMutationNodeWithRevision"
        - $ref: "#/components/schemas/VariantWorkflowMutationNodeWithRevision"
      discriminator:
        propertyName: typeName
        mapping:
          SignupTrigger: "#/components/schemas/SignupTriggerWorkflowMutationNodeWithRevision"
          EventTrigger: "#/components/schemas/EventTriggerWorkflowMutationNodeWithRevision"
          ContactPropertyTrigger: "#/components/schemas/ContactPropertyTriggerWorkflowMut\
            ationNodeWithRevision"
          AddToListTrigger: "#/components/schemas/AddToListTriggerWorkflowMutationNodeWit\
            hRevision"
          BlankTrigger: "#/components/schemas/BlankTriggerWorkflowMutationNodeWithRevision"
          AudienceFilter: "#/components/schemas/AudienceFilterWorkflowMutationNodeWithRevision"
          TimerAction: "#/components/schemas/TimerActionWorkflowMutationNodeWithRevision"
          SendEmailAction: "#/components/schemas/SendEmailActionWorkflowMutationNodeWithR\
            evision"
          ExitAction: "#/components/schemas/ExitActionWorkflowMutationNodeWithRevision"
          BranchNode: "#/components/schemas/BranchWorkflowMutationNodeWithRevision"
          ExperimentBranchNode: "#/components/schemas/ExperimentBranchWorkflowMutationNod\
            eWithRevision"
          VariantNode: "#/components/schemas/VariantWorkflowMutationNodeWithRevision"
    SignupTriggerWorkflowMutationNodeWithRevision:
      allOf:
        - $ref: "#/components/schemas/SignupTriggerWorkflowMutationNode"
        - $ref: "#/components/schemas/WorkflowMutationNodeRevision"
    EventTriggerWorkflowMutationNodeWithRevision:
      allOf:
        - $ref: "#/components/schemas/EventTriggerWorkflowMutationNode"
        - $ref: "#/components/schemas/WorkflowMutationNodeRevision"
    ContactPropertyTriggerWorkflowMutationNodeWithRevision:
      allOf:
        - $ref: "#/components/schemas/ContactPropertyTriggerWorkflowMutationNode"
        - $ref: "#/components/schemas/WorkflowMutationNodeRevision"
    AddToListTriggerWorkflowMutationNodeWithRevision:
      allOf:
        - $ref: "#/components/schemas/AddToListTriggerWorkflowMutationNode"
        - $ref: "#/components/schemas/WorkflowMutationNodeRevision"
    BlankTriggerWorkflowMutationNodeWithRevision:
      allOf:
        - $ref: "#/components/schemas/BlankTriggerWorkflowMutationNode"
        - $ref: "#/components/schemas/WorkflowMutationNodeRevision"
    AudienceFilterWorkflowMutationNodeWithRevision:
      allOf:
        - $ref: "#/components/schemas/AudienceFilterWorkflowMutationNode"
        - $ref: "#/components/schemas/WorkflowMutationNodeRevision"
    TimerActionWorkflowMutationNodeWithRevision:
      allOf:
        - $ref: "#/components/schemas/TimerActionWorkflowMutationNode"
        - $ref: "#/components/schemas/WorkflowMutationNodeRevision"
    SendEmailActionWorkflowMutationNodeWithRevision:
      allOf:
        - $ref: "#/components/schemas/SendEmailActionWorkflowMutationNode"
        - $ref: "#/components/schemas/WorkflowMutationNodeRevision"
    ExitActionWorkflowMutationNodeWithRevision:
      allOf:
        - $ref: "#/components/schemas/ExitActionWorkflowMutationNode"
        - $ref: "#/components/schemas/WorkflowMutationNodeRevision"
    BranchWorkflowMutationNodeWithRevision:
      allOf:
        - $ref: "#/components/schemas/BranchWorkflowMutationNode"
        - $ref: "#/components/schemas/WorkflowMutationNodeRevision"
    ExperimentBranchWorkflowMutationNodeWithRevision:
      allOf:
        - $ref: "#/components/schemas/ExperimentBranchWorkflowMutationNode"
        - $ref: "#/components/schemas/WorkflowMutationNodeRevision"
    VariantWorkflowMutationNodeWithRevision:
      allOf:
        - $ref: "#/components/schemas/VariantWorkflowMutationNode"
        - $ref: "#/components/schemas/WorkflowMutationNodeRevision"
    CreatedWorkflowNode:
      allOf:
        - $ref: "#/components/schemas/WorkflowMutationNodeWithRevision"
        - type: object
          properties:
            createdChildNodes:
              type: array
              description: Default child nodes created along with the requested node.
                BranchNode creation returns two AudienceFilter children.
                ExperimentBranchNode creation returns two regular VariantNode
                children and one control VariantNode.
              items:
                $ref: "#/components/schemas/WorkflowMutationNode"
    CreateWorkflowNodeResponse:
      type: object
      properties:
        node:
          $ref: "#/components/schemas/CreatedWorkflowNode"
        workflow:
          $ref: "#/components/schemas/SimplifiedWorkflow"
      required:
        - node
        - workflow
      additionalProperties: false
    AddWorkflowBranchRequest:
      type: object
      properties:
        expectedRevisionId:
          $ref: "#/components/schemas/WorkflowExpectedRevisionId"
      required:
        - expectedRevisionId
      additionalProperties: false
    AddWorkflowBranchResponse:
      type: object
      properties:
        node:
          $ref: "#/components/schemas/WorkflowMutationNodeWithRevision"
        workflow:
          $ref: "#/components/schemas/SimplifiedWorkflow"
      required:
        - node
        - workflow
      additionalProperties: false
    RerouteNodeConnectionRequest:
      type: object
      description: Reroute the source node's only outgoing connection to `newTargetNodeId`.
      properties:
        expectedRevisionId:
          $ref: "#/components/schemas/WorkflowExpectedRevisionId"
        newTargetNodeId:
          type: string
          description: The valid workflow node that should receive the connection from the
            source node.
          examples:
            - cln3c5d7e9f1g3h5i7j9k1l3
      required:
        - expectedRevisionId
        - newTargetNodeId
      additionalProperties: false
      examples:
        - expectedRevisionId: clx7a3b5c7d9e1f3g5h7i9j1
          newTargetNodeId: cln3c5d7e9f1g3h5i7j9k1l3
    RerouteNodeConnectionResponse:
      description: The updated source node, plus the latest workflow.
      allOf:
        - $ref: "#/components/schemas/WorkflowMutationNodeWithRevision"
        - type: object
          properties:
            workflow:
              $ref: "#/components/schemas/SimplifiedWorkflow"
          required:
            - workflow
      examples:
        - id: cln8p0q2r4s6t8u0v2w4x6z8
          typeName: SignupTrigger
          nextNodeIds:
            - cln3c5d7e9f1g3h5i7j9k1l3
          workflowRevisionId: clx7a3b5c7d9e1f3g5h7i9j2
          workflow:
            id: clw1a3b5c7d9e1f3g5h7i9j1
            workflowRevisionId: clx7a3b5c7d9e1f3g5h7i9j2
            status: Draft
            name: Welcome series
            description: Onboarding emails for new signups
            mailingListId: clm2k8j4h6g0f8d6s4a2b0z8
            rootNodeId: cln8p0q2r4s6t8u0v2w4x6z8
            nodes:
              cln8p0q2r4s6t8u0v2w4x6z8:
                typeName: SignupTrigger
                nextNodeIds:
                  - cln3c5d7e9f1g3h5i7j9k1l3
              cln1a3b5c7d9e1f3g5h7i9j1:
                typeName: AudienceFilter
                nextNodeIds:
                  - cln3c5d7e9f1g3h5i7j9k1l3
              cln3c5d7e9f1g3h5i7j9k1l3:
                typeName: SendEmailAction
                nextNodeIds: []
                emailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
                subject: Welcome to Acme!
    UpdateWorkflowNodeRequest:
      type: object
      properties:
        expectedRevisionId:
          $ref: "#/components/schemas/WorkflowExpectedRevisionId"
        payload:
          $ref: "#/components/schemas/UpdateWorkflowNodePayload"
      required:
        - expectedRevisionId
        - payload
      additionalProperties: false
    UpdateWorkflowNodeResponse:
      description: The updated workflow node, plus the latest simplified workflow.
      allOf:
        - $ref: "#/components/schemas/WorkflowMutationNodeWithRevision"
        - type: object
          properties:
            workflow:
              $ref: "#/components/schemas/SimplifiedWorkflow"
          required:
            - workflow
    DeleteWorkflowNodeRequest:
      type: object
      properties:
        expectedRevisionId:
          $ref: "#/components/schemas/WorkflowExpectedRevisionId"
        dryRun:
          type: boolean
          description: If `true`, the request will be validated but the workflow will not
            be modified.
        queuedContactPolicy:
          $ref: "#/components/schemas/WorkflowQueuedContactPolicy"
      required:
        - expectedRevisionId
      additionalProperties: false
    WorkflowQueuedContactDeletePreview:
      type: object
      properties:
        status:
          type: string
          enum:
            - dryRun
            - queuedContactsFound
        nodeIds:
          type: array
          items:
            type: string
          description: The IDs of the nodes that would be deleted.
        queuedContactCount:
          type: number
          description: The number of queued contacts that would be removed from the
            workflow due to the node deletion.
      required:
        - status
        - nodeIds
        - queuedContactCount
    WorkflowDeletedResponse:
      type: object
      properties:
        status:
          type: string
          enum:
            - deleted
        nodeIds:
          type: array
          items:
            type: string
        workflowRevisionId:
          $ref: "#/components/schemas/WorkflowRevisionId"
        queuedContactCount:
          type: number
          description: The number of queued contacts that were removed from the workflow
            due to the node deletion.
        workflow:
          $ref: "#/components/schemas/SimplifiedWorkflow"
      required:
        - status
        - nodeIds
        - workflowRevisionId
        - queuedContactCount
        - workflow
    DeleteWorkflowNodeResponse:
      oneOf:
        - $ref: "#/components/schemas/WorkflowQueuedContactDeletePreview"
        - $ref: "#/components/schemas/WorkflowDeletedResponse"
    ChangeWorkflowMailingListRequest:
      type: object
      properties:
        expectedRevisionId:
          $ref: "#/components/schemas/WorkflowExpectedRevisionId"
        mailingListId:
          type:
            - string
            - "null"
          description: 'The mailing list to use for the workflow. When assigning a mailing
            list, queued contacts excluded by the new list can return
            `queuedContactsFound`; retry with `queuedContactPolicy: "discard"`
            to apply the change and discard those contacts. Use `null` to clear
            the workflow mailing list; clearing does not discard queued
            contacts.'
        dryRun:
          type: boolean
          description: If `true`, the request will be validated but the workflow will not
            be modified.
        queuedContactPolicy:
          $ref: "#/components/schemas/WorkflowQueuedContactPolicy"
      required:
        - expectedRevisionId
        - mailingListId
      additionalProperties: false
    WorkflowMailingListPreview:
      type: object
      properties:
        status:
          type: string
          enum:
            - dryRun
            - queuedContactsFound
        mailingListId:
          type:
            - string
            - "null"
        queuedContactCount:
          type: number
          description: The number of queued contacts that would be removed from the
            workflow due to the mailing list changing.
      required:
        - status
        - mailingListId
        - queuedContactCount
    WorkflowMailingListUpdatedResponse:
      type: object
      properties:
        status:
          type: string
          enum:
            - updated
        mailingListId:
          type:
            - string
            - "null"
        workflowRevisionId:
          $ref: "#/components/schemas/WorkflowRevisionId"
        queuedContactCount:
          type: number
          description: The number of queued contacts that were removed from the workflow
            due to the mailing list changing.
        workflow:
          $ref: "#/components/schemas/SimplifiedWorkflow"
      required:
        - status
        - mailingListId
        - workflowRevisionId
        - queuedContactCount
        - workflow
    ChangeWorkflowMailingListResponse:
      oneOf:
        - $ref: "#/components/schemas/WorkflowMailingListPreview"
        - $ref: "#/components/schemas/WorkflowMailingListUpdatedResponse"
    EventPatternSummary:
      type: object
      properties:
        id:
          type: string
          description: The ID of the event pattern.
        eventName:
          type: string
          description: The name of the event pattern. Use this when sending events with
            the API.
        incomingWebhookPlatform:
          type:
            - string
            - "null"
          description: The platform that sent this event pattern, if the event pattern is
            from an incoming webhook. Will be `null` for custom events.
          enum:
            - clerk
            - polar
            - stripe
            - supabase
            - "null"
      required:
        - id
        - eventName
        - incomingWebhookPlatform
    ListEventPatternsResponse:
      type: object
      properties:
        pagination:
          type: object
          properties:
            totalResults:
              type: number
            returnedResults:
              type: number
            perPage:
              type: number
            totalPages:
              type: number
            nextCursor:
              type:
                - string
                - "null"
            nextPage:
              type:
                - string
                - "null"
        data:
          type: array
          items:
            $ref: "#/components/schemas/EventPatternSummary"
      required:
        - pagination
        - data
    EventPattern:
      type: object
      properties:
        id:
          type: string
        eventName:
          type: string
          description: The name of the event pattern. Use this when sending events with
            the API.
        eventProperties:
          type: array
          items:
            $ref: "#/components/schemas/WorkflowEventProperty"
          description: The properties of the event pattern, which can be used in emails.
        incomingWebhookPlatform:
          type:
            - string
            - "null"
          description: The platform that sent this event pattern, if the event pattern is
            from an incoming webhook. Will be `null` for custom events.
          enum:
            - clerk
            - polar
            - stripe
            - supabase
            - "null"
      required:
        - id
        - eventName
        - eventProperties
        - incomingWebhookPlatform
    EventPatternFailureResponse:
      type: object
      properties:
        message:
          type: string
      required:
        - message
    SimplifiedWorkflowNode:
      oneOf:
        - $ref: "#/components/schemas/SimplifiedSignupTriggerWorkflowNode"
        - $ref: "#/components/schemas/SimplifiedEventTriggerWorkflowNode"
        - $ref: "#/components/schemas/SimplifiedContactPropertyTriggerWorkflowNode"
        - $ref: "#/components/schemas/SimplifiedAddToListTriggerWorkflowNode"
        - $ref: "#/components/schemas/SimplifiedBlankTriggerWorkflowNode"
        - $ref: "#/components/schemas/SimplifiedAudienceFilterWorkflowNode"
        - $ref: "#/components/schemas/SimplifiedTimerActionWorkflowNode"
        - $ref: "#/components/schemas/SimplifiedSendEmailActionWorkflowNode"
        - $ref: "#/components/schemas/SimplifiedExitActionWorkflowNode"
        - $ref: "#/components/schemas/SimplifiedBranchWorkflowNode"
        - $ref: "#/components/schemas/SimplifiedExperimentBranchWorkflowNode"
        - $ref: "#/components/schemas/SimplifiedVariantWorkflowNode"
      discriminator:
        propertyName: typeName
    SimplifiedSignupTriggerWorkflowNode:
      type: object
      properties:
        typeName:
          type: string
          enum:
            - SignupTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
      required:
        - typeName
        - nextNodeIds
      additionalProperties: false
    SimplifiedEventTriggerWorkflowNode:
      type: object
      properties:
        typeName:
          type: string
          enum:
            - EventTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        eventName:
          type:
            - string
            - "null"
          description: The name of the event that triggers the workflow.
        reEligible:
          $ref: "#/components/schemas/WorkflowReEligible"
      required:
        - typeName
        - nextNodeIds
        - eventName
        - reEligible
      additionalProperties: false
      examples:
        - typeName: EventTrigger
          nextNodeIds:
            - cln1a3b5c7d9e1f3g5h7i9j1
          eventName: signup
          reEligible: false
    SimplifiedContactPropertyTriggerWorkflowNode:
      type: object
      properties:
        typeName:
          type: string
          enum:
            - ContactPropertyTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        contactPropertyQuery:
          oneOf:
            - $ref: "#/components/schemas/WorkflowContactPropertyQuery"
            - type: "null"
        reEligible:
          $ref: "#/components/schemas/WorkflowReEligible"
      required:
        - typeName
        - nextNodeIds
        - contactPropertyQuery
        - reEligible
      additionalProperties: false
    SimplifiedAddToListTriggerWorkflowNode:
      type: object
      properties:
        typeName:
          type: string
          enum:
            - AddToListTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        mailingListId:
          type:
            - string
            - "null"
          description: The ID of the mailing list that triggers the workflow.
        reEligible:
          $ref: "#/components/schemas/WorkflowReEligible"
      required:
        - typeName
        - nextNodeIds
        - mailingListId
        - reEligible
      additionalProperties: false
    SimplifiedBlankTriggerWorkflowNode:
      type: object
      properties:
        typeName:
          type: string
          enum:
            - BlankTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
      required:
        - typeName
        - nextNodeIds
      additionalProperties: false
    SimplifiedAudienceFilterWorkflowNode:
      type: object
      properties:
        typeName:
          type: string
          enum:
            - AudienceFilter
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
      required:
        - typeName
        - nextNodeIds
      additionalProperties: false
    SimplifiedTimerActionWorkflowNode:
      type: object
      properties:
        typeName:
          type: string
          enum:
            - TimerAction
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        amount:
          $ref: "#/components/schemas/WorkflowTimerAmount"
        unit:
          $ref: "#/components/schemas/WorkflowTimerUnit"
      required:
        - typeName
        - nextNodeIds
        - amount
        - unit
      additionalProperties: false
      examples:
        - typeName: TimerAction
          nextNodeIds:
            - cln1a3b5c7d9e1f3g5h7i9j1
          amount: 2
          unit: d
    SimplifiedSendEmailActionWorkflowNode:
      type: object
      properties:
        typeName:
          type: string
          enum:
            - SendEmailAction
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        emailMessageId:
          type:
            - string
            - "null"
          description: The ID of the email message to send. To edit this email, use the
            `POST /v1/email-messages/{emailMessageId}` endpoint.
        subject:
          type: string
          description: The subject of the email message (reference only).
      required:
        - typeName
        - nextNodeIds
        - emailMessageId
        - subject
      additionalProperties: false
      examples:
        - typeName: SendEmailAction
          nextNodeIds: []
          emailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
          subject: Welcome to Acme!
    SimplifiedExitActionWorkflowNode:
      type: object
      properties:
        typeName:
          type: string
          enum:
            - ExitAction
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
      required:
        - typeName
        - nextNodeIds
      additionalProperties: false
    SimplifiedBranchWorkflowNode:
      type: object
      properties:
        typeName:
          type: string
          enum:
            - BranchNode
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
      required:
        - typeName
        - nextNodeIds
      additionalProperties: false
    SimplifiedExperimentBranchWorkflowNode:
      type: object
      properties:
        typeName:
          type: string
          enum:
            - ExperimentBranchNode
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        samplingRate:
          type: number
          description: The percentage of contacts that will be sent to variant branches,
            between `0` and `100`. The remaining percentage will be sent to the
            control branch.
      required:
        - typeName
        - nextNodeIds
        - samplingRate
      additionalProperties: false
    SimplifiedVariantWorkflowNode:
      type: object
      properties:
        typeName:
          type: string
          enum:
            - VariantNode
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        isControl:
          type: boolean
          description: Whether this is the control variant of an experiment.
      required:
        - typeName
        - nextNodeIds
        - isControl
      additionalProperties: false
    WorkflowNode:
      oneOf:
        - $ref: "#/components/schemas/SignupTriggerWorkflowNode"
        - $ref: "#/components/schemas/EventTriggerWorkflowNode"
        - $ref: "#/components/schemas/ContactPropertyTriggerWorkflowNode"
        - $ref: "#/components/schemas/AddToListTriggerWorkflowNode"
        - $ref: "#/components/schemas/BlankTriggerWorkflowNode"
        - $ref: "#/components/schemas/AudienceFilterWorkflowNode"
        - $ref: "#/components/schemas/TimerActionWorkflowNode"
        - $ref: "#/components/schemas/SendEmailActionWorkflowNode"
        - $ref: "#/components/schemas/ExitActionWorkflowNode"
        - $ref: "#/components/schemas/BranchWorkflowNode"
        - $ref: "#/components/schemas/ExperimentBranchWorkflowNode"
        - $ref: "#/components/schemas/VariantWorkflowNode"
      discriminator:
        propertyName: typeName
    WorkflowNodeWithRevision:
      description: Detailed workflow node returned from read operations. The exact
        fields depend on `typeName`.
      allOf:
        - $ref: "#/components/schemas/WorkflowNode"
        - type: object
          properties:
            workflowRevisionId:
              $ref: "#/components/schemas/NullableWorkflowRevisionId"
          required:
            - workflowRevisionId
    SignupTriggerWorkflowNode:
      type: object
      properties:
        id:
          type: string
          examples:
            - cln8p0q2r4s6t8u0v2w4x6z8
        workflowId:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
        typeName:
          type: string
          enum:
            - SignupTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
      required:
        - id
        - workflowId
        - typeName
        - nextNodeIds
      additionalProperties: false
    EventTriggerWorkflowNode:
      type: object
      properties:
        id:
          type: string
          examples:
            - cln8p0q2r4s6t8u0v2w4x6z8
        workflowId:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
        typeName:
          type: string
          enum:
            - EventTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        eventName:
          type: string
          examples:
            - signup
          description: The name of the event pattern that triggers this node.
        eventProperties:
          type: array
          items:
            $ref: "#/components/schemas/WorkflowEventProperty"
          description: The properties of the event pattern, which can be used in emails.
        reEligible:
          $ref: "#/components/schemas/WorkflowReEligible"
      required:
        - id
        - workflowId
        - typeName
        - nextNodeIds
        - reEligible
      additionalProperties: false
    ContactPropertyTriggerWorkflowNode:
      type: object
      properties:
        id:
          type: string
          examples:
            - cln8p0q2r4s6t8u0v2w4x6z8
        workflowId:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
        typeName:
          type: string
          enum:
            - ContactPropertyTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        contactPropertyQuery:
          oneOf:
            - $ref: "#/components/schemas/WorkflowContactPropertyQuery"
            - type: "null"
        reEligible:
          $ref: "#/components/schemas/WorkflowReEligible"
      required:
        - id
        - workflowId
        - typeName
        - nextNodeIds
        - contactPropertyQuery
        - reEligible
      additionalProperties: false
    AddToListTriggerWorkflowNode:
      type: object
      properties:
        id:
          type: string
          examples:
            - cln8p0q2r4s6t8u0v2w4x6z8
        workflowId:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
        typeName:
          type: string
          enum:
            - AddToListTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        mailingListId:
          type:
            - string
            - "null"
          examples:
            - clm2k8j4h6g0f8d6s4a2b0z8
            - null
          description: The ID of the mailing list that triggers the workflow.
        reEligible:
          $ref: "#/components/schemas/WorkflowReEligible"
      required:
        - id
        - workflowId
        - typeName
        - nextNodeIds
        - mailingListId
        - reEligible
      additionalProperties: false
    BlankTriggerWorkflowNode:
      type: object
      properties:
        id:
          type: string
          examples:
            - cln8p0q2r4s6t8u0v2w4x6z8
        workflowId:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
        typeName:
          type: string
          enum:
            - BlankTrigger
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
      required:
        - id
        - workflowId
        - typeName
        - nextNodeIds
      additionalProperties: false
    AudienceFilterWorkflowNode:
      type: object
      properties:
        id:
          type: string
          examples:
            - cln8p0q2r4s6t8u0v2w4x6z8
        workflowId:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
        typeName:
          type: string
          enum:
            - AudienceFilter
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        audienceFilter:
          $ref: "#/components/schemas/AudienceFilter"
        audienceSegmentId:
          type: string
        appliesDownstream:
          description: If `true`, the audience filter will apply to all downstream nodes.
            If `false`, the audience filter will only apply to the current node.
            Matches the "Filter scope" option in the UI.
          type: boolean
      required:
        - id
        - workflowId
        - typeName
        - nextNodeIds
        - appliesDownstream
      additionalProperties: false
    TimerActionWorkflowNode:
      type: object
      properties:
        id:
          type: string
          examples:
            - cln8p0q2r4s6t8u0v2w4x6z8
        workflowId:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
        typeName:
          type: string
          enum:
            - TimerAction
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        amount:
          $ref: "#/components/schemas/WorkflowTimerAmount"
        unit:
          $ref: "#/components/schemas/WorkflowTimerUnit"
      required:
        - id
        - workflowId
        - typeName
        - nextNodeIds
        - amount
        - unit
      additionalProperties: false
    SendEmailActionWorkflowNode:
      type: object
      properties:
        id:
          type: string
          examples:
            - cln8p0q2r4s6t8u0v2w4x6z8
        workflowId:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
        typeName:
          type: string
          enum:
            - SendEmailAction
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        emailMessageId:
          type: string
          examples:
            - cle5f7g9h1i3j5k7l9m1n3p5
          description: The ID of the email message to send. To edit this email, use the
            `POST /v1/email-messages/{emailMessageId}` endpoint.
        subject:
          type: string
          examples:
            - Welcome to Acme!
      required:
        - id
        - workflowId
        - typeName
        - nextNodeIds
        - emailMessageId
        - subject
      additionalProperties: false
    ExitActionWorkflowNode:
      type: object
      properties:
        id:
          type: string
          examples:
            - cln8p0q2r4s6t8u0v2w4x6z8
        workflowId:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
        typeName:
          type: string
          enum:
            - ExitAction
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
      required:
        - id
        - workflowId
        - typeName
        - nextNodeIds
      additionalProperties: false
    BranchWorkflowNode:
      type: object
      properties:
        id:
          type: string
          examples:
            - cln8p0q2r4s6t8u0v2w4x6z8
        workflowId:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
        typeName:
          type: string
          enum:
            - BranchNode
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
      required:
        - id
        - workflowId
        - typeName
        - nextNodeIds
      additionalProperties: false
    ExperimentBranchWorkflowNode:
      type: object
      properties:
        id:
          type: string
          examples:
            - cln8p0q2r4s6t8u0v2w4x6z8
        workflowId:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
        typeName:
          type: string
          enum:
            - ExperimentBranchNode
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        samplingRate:
          type: number
          description: The percentage of contacts that will be sent to variant branches,
            between `0` and `100`. The remaining percentage will be sent to the
            control branch. `100` sends all contacts to variant branches.
      required:
        - id
        - workflowId
        - typeName
        - nextNodeIds
        - samplingRate
      additionalProperties: false
    VariantWorkflowNode:
      type: object
      properties:
        id:
          type: string
          examples:
            - cln8p0q2r4s6t8u0v2w4x6z8
        workflowId:
          type: string
          examples:
            - clw1a3b5c7d9e1f3g5h7i9j1
        typeName:
          type: string
          enum:
            - VariantNode
        nextNodeIds:
          $ref: "#/components/schemas/WorkflowNextNodeIds"
        isControl:
          type: boolean
          description: Whether this is the control variant of an experiment.
      required:
        - id
        - workflowId
        - typeName
        - nextNodeIds
      additionalProperties: false
    WorkflowEventProperty:
      type: object
      properties:
        name:
          type: string
        type:
          type: string
          enum:
            - string
            - number
            - boolean
            - date
      required:
        - name
        - type
    WorkflowContactPropertyQuery:
      type: object
      description: Define the contact property change that triggers the workflow. In
        update requests, `key` must resolve to an existing contact property that
        is available for Contact Updated triggers. Hidden or unsupported fields,
        such as `createdAt`, `notes`, and computed contact properties, are
        rejected.
      properties:
        key:
          type: string
          description: The camel-cased `key` of the contact property to query. The
            property must exist for the team and must be available for Contact
            Updated triggers.
          examples:
            - firstName
            - email
            - planName
        is:
          description: Comparison for the new contact property value after the update.
          $ref: "#/components/schemas/WorkflowContactPropertyComparison"
        was:
          description: Comparison for the previous contact property value before the update.
          $ref: "#/components/schemas/WorkflowContactPropertyComparison"
      required:
        - key
        - is
        - was
    WorkflowContactPropertyComparison:
      type: object
      description: For Contact Updated triggers, the API validates `operator` against
        the selected contact property's type and the side of the comparison. The
        `was` comparison can use any operator supported by the selected property
        type. The `is` comparison uses the same operators, except number and
        boolean properties cannot use `empty`. String properties support `any`,
        `equal`, `not_equal`, `contains`, `not_contains`, `empty`, and
        `not_empty`. Number properties support `any`, `greater_than`,
        `less_than`, `numeric_equal`, `numeric_not_equal`, `empty`, and
        `not_empty`. Boolean properties support `any`, `true`, `false`, `empty`,
        and `not_empty`. Date properties support `any`, `empty`, `not_empty`,
        `after`, `before`, and `between`.
      properties:
        value:
          oneOf:
            - type: string
            - type: number
            - type: boolean
        operator:
          type: string
          description: The comparison operator. It must be valid for the selected contact
            property's type and for the `is` or `was` side of the comparison.
            Number and boolean properties allow `empty` on `was`, but not on
            `is`.
          enum:
            - any
            - contains
            - not_contains
            - empty
            - not_empty
            - equal
            - not_equal
            - greater_than
            - less_than
            - "true"
            - "false"
            - numeric_equal
            - numeric_not_equal
            - after
            - before
            - between
      required:
        - value
        - operator
    WorkflowTimerAmount:
      type: number
      description: The amount of time to wait before triggering the next node. Set to
        `0` to move to the next node immediately.
    WorkflowTimerUnit:
      type: string
      enum:
        - m
        - h
        - d
      description: The unit of time for the timer action node. m = minutes, h = hours,
        d = days.
    WorkflowFailureResponse:
      type: object
      properties:
        message:
          type: string
      required:
        - message
      examples:
        - message: Workflow not found.
    GroupResponse:
      type: object
      properties:
        id:
          type: string
          description: The ID of the group.
          examples:
            - clg7n5p3q1r9s7t5u3v1w9y7
        name:
          type: string
          description: The name of the group.
          examples:
            - Onboarding
        description:
          type: string
          description: The description of the group.
          examples:
            - Top of funnel campaigns
        createdAt:
          type: string
          format: date-time
          examples:
            - 2025-06-29T07:47:39.370Z
          description: ISO 8601 timestamp for when the group was created.
        updatedAt:
          type: string
          format: date-time
          examples:
            - 2025-06-29T07:47:39.370Z
          description: ISO 8601 timestamp for when the group was last updated.
      required:
        - id
        - name
        - description
        - createdAt
        - updatedAt
      examples:
        - id: clg7n5p3q1r9s7t5u3v1w9y7
          name: Onboarding
          description: Top of funnel campaigns
          createdAt: 2025-06-29T07:47:39.370Z
          updatedAt: 2025-06-29T07:47:39.370Z
    ListGroupsResponse:
      type: object
      properties:
        pagination:
          $ref: "#/components/schemas/Pagination"
        data:
          type: array
          items:
            $ref: "#/components/schemas/GroupResponse"
      required:
        - pagination
        - data
      examples:
        - pagination:
            totalResults: 2
            returnedResults: 2
            perPage: 20
            totalPages: 1
            nextCursor: null
            nextPage: null
          data:
            - id: clg7n5p3q1r9s7t5u3v1w9y7
              name: Onboarding
              description: Top of funnel campaigns
              createdAt: 2025-06-29T07:47:39.370Z
              updatedAt: 2025-06-29T07:47:39.370Z
            - id: clg8m4n6p8q0r2s4t6u8v0w2
              name: Retention
              description: ""
              createdAt: 2025-06-30T12:00:00.000Z
              updatedAt: 2025-06-30T12:00:00.000Z
    CreateGroupRequest:
      type: object
      properties:
        name:
          type: string
          description: The group name. Cannot be the reserved name "Unsorted".
          examples:
            - Newsletters
        description:
          type: string
          description: An optional description for the group.
          examples:
            - Monthly newsletter campaigns
      required:
        - name
      additionalProperties: false
      examples:
        - name: Newsletters
          description: Monthly newsletter campaigns
    UpdateGroupRequest:
      type: object
      description: At least one field must be provided.
      properties:
        name:
          type: string
          description: The group name. Cannot be the reserved name "Unsorted".
        description:
          type: string
          description: A description for the group.
      additionalProperties: false
    GroupFailureResponse:
      type: object
      properties:
        message:
          type: string
          examples:
            - Group not found.
      required:
        - message
      examples:
        - message: Group not found.
    UpdateEmailMessageRequest:
      type: object
      properties:
        expectedRevisionId:
          type: string
          description: The `contentRevisionId` you last fetched, or the
            `emailMessageContentRevisionId` you received when creating the
            campaign.
        subject:
          type: string
        previewText:
          type: string
        fromName:
          type: string
        fromEmail:
          type: string
          description: The email sender email address, without the team's sending domain.
          examples:
            - hello
        replyToEmail:
          type: string
          description: Reply-to email. Must be empty or a valid email address.
        ccEmail:
          type: string
          description: CC email address. Requires the team to have CC/BCC enabled.
        bccEmail:
          type: string
          description: BCC email address. Requires the team to have CC/BCC enabled.
        languageCode:
          type: string
          description: ISO 639-1 language code for the email, e.g. `en` or `fr`.
        emailFormat:
          type: string
          enum:
            - styled
            - plain
          description: The rendering format of the email.
        lmx:
          type: string
          description: The email body serialized as LMX. Styles must be embedded in the
            LMX `<Style />` tag.
        contactPropertiesFallbacks:
          type: object
          description: "Fallback values for contact properties, keyed by property name.
            Per-key merge: a string value sets the fallback, a null value
            deletes it, and keys omitted from the map are left unchanged."
          additionalProperties:
            type:
              - string
              - "null"
        eventPropertiesFallbacks:
          type: object
          description: "Fallback values for event properties, keyed by property name.
            Per-key merge: a string value sets the fallback, a null value
            deletes it, and keys omitted from the map are left unchanged."
          additionalProperties:
            type:
              - string
              - "null"
        dataVariablesFallbacks:
          type: object
          description: "Fallback values for data variables, keyed by variable name.
            Per-key merge: a string value sets the fallback, a null value
            deletes it, and keys omitted from the map are left unchanged."
          additionalProperties:
            type:
              - string
              - "null"
      additionalProperties: false
      examples:
        - expectedRevisionId: clrev1s10n2i3d4e5f6g7h8
          subject: Spring product updates
          previewText: See what's new this season
          fromName: Acme Team
          fromEmail: hello
          replyToEmail: support@company.com
          emailFormat: styled
          lmx: <Paragraph>Hello, {firstName}!</Paragraph>
          contactPropertiesFallbacks:
            firstName: there
    EmailMessageResponse:
      type: object
      properties:
        id:
          type: string
          examples:
            - cle5f7g9h1i3j5k7l9m1n3p5
          description: The ID of the email message.
        campaignId:
          type: string
          description: The campaign this email message belongs to. Present only when the
            message belongs to a campaign (mutually exclusive with
            `transactionalId`).
          examples:
            - clc4m6n8p0q2r4s6t8u0v2x4
        transactionalId:
          type: string
          description: The transactional email this email message belongs to. Present only
            when the message belongs to a transactional email (mutually
            exclusive with `campaignId`).
        subject:
          type: string
          description: The email subject.
          examples:
            - Spring product updates
        previewText:
          type: string
          description: The email preview text.
          examples:
            - See what's new this season
        fromName:
          type: string
          description: The email sender name.
          examples:
            - Acme Team
        fromEmail:
          type: string
          description: The email sender email address, without the team's sending domain.
          examples:
            - hello
        replyToEmail:
          type: string
          description: The email reply-to address.
          examples:
            - support@company.com
        ccEmail:
          type: string
          description: The email CC address. Only present when set.
        bccEmail:
          type: string
          description: The email BCC address. Only present when set.
        languageCode:
          type: string
          description: ISO 639-1 language code for the email, e.g. `en` or `fr`. Only
            present when set.
        emailFormat:
          type: string
          enum:
            - styled
            - plain
          description: The rendering format of the email.
          examples:
            - styled
        lmx:
          type: string
          description: The email body serialized as LMX.
          examples:
            - <Paragraph>Hello, {firstName}!</Paragraph>
        contentRevisionId:
          type:
            - string
            - "null"
          description: The current content revision. Pass this as `expectedRevisionId` on
            your next update.
          examples:
            - clrev1s10n2i3d4e5f6g7h8
        updatedAt:
          type: string
          format: date-time
          examples:
            - 2025-06-29T07:47:39.370Z
        contactPropertiesFallbacks:
          type: object
          description: Fallback values for contact properties. Only present when set.
          additionalProperties:
            type: string
        eventPropertiesFallbacks:
          type: object
          description: Fallback values for event properties. Only present when set.
          additionalProperties:
            type: string
        dataVariablesFallbacks:
          type: object
          description: Fallback values for data variables. Only present when set.
          additionalProperties:
            type: string
        warnings:
          type: array
          description: Non-fatal issues raised while compiling the submitted LMX. Only
            present on update responses when warnings were produced.
          items:
            type: object
            properties:
              rule:
                type: string
              severity:
                type: string
                enum:
                  - warning
              message:
                type: string
              path:
                type: string
            required:
              - rule
              - severity
              - message
      required:
        - id
        - subject
        - previewText
        - fromName
        - fromEmail
        - replyToEmail
        - emailFormat
        - lmx
        - contentRevisionId
        - updatedAt
      examples:
        - id: cle5f7g9h1i3j5k7l9m1n3p5
          campaignId: clc4m6n8p0q2r4s6t8u0v2x4
          subject: Spring product updates
          previewText: See what's new this season
          fromName: Acme Team
          fromEmail: hello
          replyToEmail: support@company.com
          emailFormat: styled
          lmx: <Paragraph>Hello, {firstName}!</Paragraph>
          contentRevisionId: clrev1s10n2i3d4e5f6g7h8
          updatedAt: 2025-06-29T07:47:39.370Z
    EmailMessageFailureResponse:
      type: object
      properties:
        message:
          type: string
      required:
        - message
      examples:
        - message: Email message not found.
    EmailMessagePreviewRequest:
      type: object
      properties:
        emails:
          type: array
          minItems: 1
          items:
            type: string
          description: One or more addresses to send the preview to.
        contactProperties:
          type: object
          additionalProperties:
            type: string
          description: Contact property values to render. Accepted for campaign and
            workflow previews.
          example:
            firstName: Alex
        eventProperties:
          type: object
          additionalProperties:
            type: string
          description: Event property values to render. Accepted for workflow previews only.
          example:
            planName: Pro
        dataVariables:
          type: object
          additionalProperties:
            type: string
          description: Transactional data variables to render. Accepted for transactional
            previews only.
          example:
            loginUrl: https://app.company.com/login
      required:
        - emails
      additionalProperties: false
      examples:
        - emails:
            - alex@company.com
          contactProperties:
            firstName: Alex
          eventProperties:
            planName: Pro
          dataVariables:
            loginUrl: https://app.company.com/login
    EmailMessagePreviewResponse:
      type: object
      properties:
        id:
          type: string
          description: The ID of the email message the preview was sent for.
          examples:
            - cle5f7g9h1i3j5k7l9m1n3p5
      required:
        - id
      examples:
        - id: cle5f7g9h1i3j5k7l9m1n3p5
    EmailMessageGuardianResponse:
      type: object
      properties:
        errors:
          type: array
          description: Validation errors. These must be resolved before the email can be
            published.
          items:
            $ref: "#/components/schemas/GuardianRule"
        warnings:
          type: array
          description: Validation warnings. These are advisory and do not block publishing.
          items:
            $ref: "#/components/schemas/GuardianRule"
      required:
        - errors
        - warnings
      example:
        errors:
          - rule: missingButtonHrefs
            title: Missing button link
            description: Buttons won't work without href value
            items:
              - label: Click here
          - rule: missingLinkHrefs
            title: Missing text link
            description: Links won't work without href value
            items:
              - label: See more
        warnings: []
    GuardianRule:
      type: object
      properties:
        rule:
          type: string
          description: The identifier of the Guardian rule that fired.
          enum:
            - unsupportedContactProperties
            - missingFallbackContactProperties
            - unsupportedEventProperties
            - missingFallbackEventProperties
            - unsupportedDataVariables
            - invalidCustomDataVariables
            - missingRequiredDataVariables
            - missingButtonHrefs
            - invalidButtonHrefs
            - shortenedYouTubeButtonHrefs
            - missingLinkHrefs
            - invalidLinkHrefs
            - shortenedYouTubeLinkHrefs
            - shortenedYouTubeImageHrefs
            - emailWithoutMailtoButtonHrefs
            - emailWithoutMailtoLinkHrefs
            - emailWithoutMailtoImageHrefs
            - bareArrayNodes
            - missingSocialIconHrefs
        title:
          type: string
          description: A short summary of the rule.
        description:
          type: string
          description: A longer explanation of why the issue matters.
        items:
          type: array
          description: The specific elements that triggered the rule.
          items:
            type: object
            properties:
              label:
                type: string
                description: A human-readable label for the item (for example, link text or a
                  property name).
              codeName:
                type: string
                description: Machine-readable identifier when the rule refers to a property or
                  variable, when applicable.
                example: firstName
            required:
              - label
      required:
        - rule
        - title
        - description
        - items
    CreateUploadRequest:
      type: object
      properties:
        contentType:
          type: string
          description: The MIME type of the file to upload. Supported types are
            `image/jpeg`, `image/png`, `image/gif` and `image/webp`.
          examples:
            - image/png
        contentLength:
          type: integer
          description: The size of the file in bytes. Must be a positive integer no
            greater than 4,000,000 bytes.
          examples:
            - 102400
      required:
        - contentType
        - contentLength
      additionalProperties: false
    CreateUploadResponse:
      type: object
      properties:
        emailAssetId:
          type: string
          examples:
            - cla3s5s7e9t1i3d5f7g9h1j3
          description: The ID of the created asset. Pass this as `emailAssetId` to `POST
            /v1/uploads/{emailAssetId}/complete` once the file has been
            uploaded.
        presignedUrl:
          type: string
          description: The pre-signed URL to upload the file to with an HTTP `PUT`
            request. Send the same `Content-Type` and `Content-Length` used in
            the create request.
          examples:
            - https://loops-assets.s3.amazonaws.com/uploads/cla3s5s7e9t1i3d5f7g9h1j3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...
      required:
        - emailAssetId
        - presignedUrl
      examples:
        - emailAssetId: cla3s5s7e9t1i3d5f7g9h1j3
          presignedUrl: https://loops-assets.s3.amazonaws.com/uploads/cla3s5s7e9t1i3d5f7g9h1j3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...
    CompleteUploadResponse:
      type: object
      properties:
        emailAssetId:
          type: string
          examples:
            - cla3s5s7e9t1i3d5f7g9h1j3
          description: The ID of the created asset.
        finalUrl:
          type: string
          description: The public URL of the uploaded asset.
          examples:
            - https://assets.loops.so/cla3s5s7e9t1i3d5f7g9h1j3/logo.png
      required:
        - emailAssetId
        - finalUrl
      examples:
        - emailAssetId: cla3s5s7e9t1i3d5f7g9h1j3
          finalUrl: https://assets.loops.so/cla3s5s7e9t1i3d5f7g9h1j3/logo.png
    UploadLimitExceededFailureResponse:
      type: object
      properties:
        message:
          type: string
          examples:
            - "Upload limit exceeded: max 50 uploads per 24 hours. Please
              contact support if you need to increase your upload limit."
        maxUploads:
          type: integer
          description: The maximum number of uploads allowed per window.
          examples:
            - 50
        windowHours:
          type: integer
          description: The number of hours in the upload limit window.
          examples:
            - 24
    UploadFailureResponse:
      type: object
      properties:
        message:
          type: string
          examples:
            - Unsupported content type.
        supportedContentTypes:
          type: array
          description: Present when the request was rejected for an unsupported
            `contentType`. Lists the accepted MIME types.
          items:
            type: string
        maxBytes:
          type: integer
          description: Present when the upload exceeds the size limit. The maximum allowed
            size in bytes.
      required:
        - message
      examples:
        - message: Unsupported content type.
          supportedContentTypes:
            - image/jpeg
            - image/png
            - image/gif
            - image/webp
          maxBytes: 4000000
    Pagination:
      type: object
      properties:
        totalResults:
          type: number
          examples:
            - 2
        returnedResults:
          type: number
          examples:
            - 2
        perPage:
          type: number
          examples:
            - 20
        totalPages:
          type: number
          examples:
            - 1
        nextCursor:
          type:
            - string
            - "null"
          examples:
            - null
        nextPage:
          type:
            - string
            - "null"
          examples:
            - null
      required:
        - totalResults
        - returnedResults
        - perPage
        - totalPages
        - nextCursor
        - nextPage
      examples:
        - totalResults: 2
          returnedResults: 2
          perPage: 20
          totalPages: 1
          nextCursor: null
          nextPage: null
    WebhookContactIdentity:
      type: object
      required:
        - id
        - email
        - userId
      properties:
        id:
          type: string
        email:
          type: string
        userId:
          type:
            - string
            - "null"
    WebhookBasePayload:
      type: object
      required:
        - eventName
        - eventTime
        - webhookSchemaVersion
        - contactIdentity
      properties:
        eventName:
          type: string
        eventTime:
          type: integer
          description: Unix timestamp in seconds.
        webhookSchemaVersion:
          type: string
          const: 1.0.0
        contactIdentity:
          $ref: "#/components/schemas/WebhookContactIdentity"
    WebhookContact:
      type: object
      required:
        - id
        - email
        - firstName
        - lastName
        - source
        - subscribed
        - userGroup
        - userId
        - mailingLists
        - optInStatus
      properties:
        id:
          type: string
        email:
          type: string
        firstName:
          type:
            - string
            - "null"
        lastName:
          type:
            - string
            - "null"
        source:
          type: string
        subscribed:
          type: boolean
        userGroup:
          type: string
        userId:
          type:
            - string
            - "null"
        notes:
          type:
            - string
            - "null"
        mailingLists:
          type: object
          description: An object of mailing list IDs and boolean subscription statuses.
          additionalProperties:
            type: boolean
        optInStatus:
          type:
            - string
            - "null"
          description: Double opt-in status.
          enum:
            - accepted
            - pending
            - rejected
            - null
      additionalProperties: true
      description: Full contact object, including custom properties.
    WebhookEmail:
      type: object
      required:
        - id
        - emailMessageId
        - subject
      properties:
        id:
          type: string
          description: The ID of the email.
        emailMessageId:
          type: string
          description: The ID of the sent version of the campaign, workflow or
            transactional email.
        subject:
          type: string
          description: The subject of the email.
    WebhookMailingList:
      type: object
      description: Details of the mailing list.
      required:
        - id
        - name
        - description
        - isPublic
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type:
            - string
            - "null"
        isPublic:
          type: boolean
    WebhookEmailMetricPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookBasePayload"
        - type: object
          required:
            - email
            - sourceType
          properties:
            email:
              $ref: "#/components/schemas/WebhookEmail"
            sourceType:
              type: string
              enum:
                - loop
                - campaign
                - transactional
              description: The type of email this event relates to. Workflow emails use
                `loop`.
            campaignId:
              type: string
              description: The ID of the campaign if `sourceType` is `campaign`.
            loopId:
              type: string
              description: The ID of the workflow if `sourceType` is `loop`.
            transactionalId:
              type: string
              description: The ID of the transactional email if `sourceType` is
                `transactional`.
    WebhookMarketingEmailMetricPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookBasePayload"
        - type: object
          required:
            - email
            - sourceType
          properties:
            email:
              $ref: "#/components/schemas/WebhookEmail"
            sourceType:
              type: string
              enum:
                - loop
                - campaign
              description: The type of email this event relates to. Workflow emails use
                `loop`. Not available for transactional emails.
            campaignId:
              type: string
              description: The ID of the campaign if `sourceType` is `campaign`.
            loopId:
              type: string
              description: The ID of the workflow if `sourceType` is `loop`.
    WebhookContactUnsubscribedPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookBasePayload"
        - type: object
          required:
            - eventName
          properties:
            eventName:
              type: string
              const: contact.unsubscribed
    WebhookContactCreatedPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookBasePayload"
        - type: object
          required:
            - eventName
            - contact
          properties:
            eventName:
              type: string
              const: contact.created
            contact:
              $ref: "#/components/schemas/WebhookContact"
    WebhookContactDeletedPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookBasePayload"
        - type: object
          required:
            - eventName
          properties:
            eventName:
              type: string
              const: contact.deleted
    WebhookContactMailingListSubscribedPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookBasePayload"
        - type: object
          required:
            - eventName
            - mailingList
          properties:
            eventName:
              type: string
              const: contact.mailingList.subscribed
            mailingList:
              $ref: "#/components/schemas/WebhookMailingList"
    WebhookContactMailingListUnsubscribedPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookBasePayload"
        - type: object
          required:
            - eventName
            - mailingList
          properties:
            eventName:
              type: string
              const: contact.mailingList.unsubscribed
            mailingList:
              $ref: "#/components/schemas/WebhookMailingList"
    WebhookTransactionalEmailSentPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookBasePayload"
        - type: object
          required:
            - eventName
            - transactionalId
            - email
            - transactionalName
          properties:
            eventName:
              type: string
              const: transactional.email.sent
            transactionalId:
              type: string
            transactionalName:
              type: string
            email:
              $ref: "#/components/schemas/WebhookEmail"
    WebhookCampaignEmailSentPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookBasePayload"
        - type: object
          required:
            - eventName
            - campaignId
            - email
            - mailingLists
            - campaignName
          properties:
            eventName:
              type: string
              const: campaign.email.sent
            campaignId:
              type: string
            campaignName:
              type: string
            email:
              $ref: "#/components/schemas/WebhookEmail"
            mailingLists:
              type: array
              description: The mailing list(s) the email was sent to, or an empty array.
              items:
                $ref: "#/components/schemas/WebhookMailingList"
    WebhookLoopEmailSentPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookBasePayload"
        - type: object
          required:
            - eventName
            - loopId
            - email
            - mailingLists
            - loopName
          properties:
            eventName:
              type: string
              const: loop.email.sent
            loopId:
              type: string
              description: The ID of the workflow.
            loopName:
              type: string
              description: The name of the workflow.
            email:
              $ref: "#/components/schemas/WebhookEmail"
            mailingLists:
              type: array
              description: The mailing list(s) the email was sent to, or an empty array.
              items:
                $ref: "#/components/schemas/WebhookMailingList"
    WebhookEmailDeliveredPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookEmailMetricPayload"
        - type: object
          required:
            - eventName
          properties:
            eventName:
              type: string
              const: email.delivered
    WebhookEmailSoftBouncedPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookEmailMetricPayload"
        - type: object
          required:
            - eventName
          properties:
            eventName:
              type: string
              const: email.softBounced
    WebhookEmailHardBouncedPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookEmailMetricPayload"
        - type: object
          required:
            - eventName
          properties:
            eventName:
              type: string
              const: email.hardBounced
    WebhookEmailClickedPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookMarketingEmailMetricPayload"
        - type: object
          required:
            - eventName
          properties:
            eventName:
              type: string
              const: email.clicked
    WebhookEmailUnsubscribedPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookMarketingEmailMetricPayload"
        - type: object
          required:
            - eventName
          properties:
            eventName:
              type: string
              const: email.unsubscribed
    WebhookEmailResubscribedPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookMarketingEmailMetricPayload"
        - type: object
          required:
            - eventName
          properties:
            eventName:
              type: string
              const: email.resubscribed
    WebhookEmailOpenedPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookMarketingEmailMetricPayload"
        - type: object
          required:
            - eventName
          properties:
            eventName:
              type: string
              const: email.opened
    WebhookEmailSpamReportedPayload:
      allOf:
        - $ref: "#/components/schemas/WebhookEmailMetricPayload"
        - type: object
          required:
            - eventName
          properties:
            eventName:
              type: string
              const: email.spamReported
    WebhookTestingTestEventPayload:
      type: object
      required:
        - eventName
        - eventTime
        - message
        - webhookSchemaVersion
      properties:
        eventName:
          type: string
          const: testing.testEvent
        eventTime:
          type: integer
          description: Unix timestamp in seconds.
        message:
          type: string
          const: test
        webhookSchemaVersion:
          type: string
          const: 1.0.0
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
  parameters:
    WebhookId:
      name: webhook-id
      in: header
      required: true
      schema:
        type: string
      description: Unique message ID. Use to deduplicate deliveries.
    WebhookTimestamp:
      name: webhook-timestamp
      in: header
      required: true
      schema:
        type: string
      description: Unix timestamp of when the message was sent.
    WebhookSignature:
      name: webhook-signature
      in: header
      required: true
      schema:
        type: string
      description: HMAC signature for verifying the request. Verify using your
        endpoint signing secret from the Loops dashboard.
