Loops Campaigns API

Create, target, schedule and update email campaigns. 4 operation(s) in the Loops REST API v1 (OpenAPI 1.21.6).

OpenAPI Specification

loops-campaigns-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Loops OpenAPI Spec Campaigns API
  description: This is the OpenAPI Spec for the [Loops API](https://loops.so/docs/api).
  version: 1.21.6
servers:
- url: https://app.loops.so/api/v1
tags:
- name: Campaigns
  description: Create and manage email campaigns
paths:
  /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: []
  /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: []
components:
  schemas:
    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
    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
    AudienceFilterCondition:
      oneOf:
      - $ref: '#/components/schemas/PropertyCondition'
      - $ref: '#/components/schemas/OptInCondition'
      - $ref: '#/components/schemas/ActivityCondition'
      discriminator:
        propertyName: type
    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
    CampaignFailureResponse:
      type: object
      properties:
        message:
          type: string
      required:
      - message
      examples:
      - message: Campaign not found.
    CampaignResponse:
      type: object
      properties:
        id:
          type: string
          description: The ID of the campaign.
          examples:
          - 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-29 07:47:39.370000+00:00
          description: ISO 8601 timestamp for when the campaign was created.
        updatedAt:
          type: string
          format: date-time
          examples:
          - 2025-06-29 07:47:39.370000+00:00
          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
      - name
      - status
      - createdAt
      - updatedAt
      - emailMessageId
      - campaignGroupId
      - mailingListId
      - audienceSegmentId
      - audienceFilter
      - scheduling
      examples:
      - id: clc4m6n8p0q2r4s6t8u0v2x4
        name: Spring announcement
        status: Draft
        createdAt: 2025-06-29 07:47:39.370000+00:00
        updatedAt: 2025-06-29 07:47:39.370000+00:00
        emailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
        campaignGroupId: clg7n5p3q1r9s7t5u3v1w9y7
        mailingListId: clm2k8j4h6g0f8d6s4a2b0z8
        audienceSegmentId: null
        audienceFilter: null
        scheduling:
          method: now
          timestamp: null
    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-15 14:00:00+00:00
    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-15 14:00:00+00:00
    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
        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-29 07:47:39.370000+00:00
          description: ISO 8601 timestamp for when the campaign was created.
        updatedAt:
          type: string
          format: date-time
          examples:
          - 2025-06-29 07:47:39.370000+00:00
          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
      - name
      - status
      - createdAt
      - updatedAt
      - emailMessageId
      - emailMessageContentRevisionId
      - campaignGroupId
      - mailingListId
      - audienceSegmentId
      - audienceFilter
      - scheduling
      examples:
      - id: clc4m6n8p0q2r4s6t8u0v2x4
        name: Spring announcement
        status: Draft
        createdAt: 2025-06-29 07:47:39.370000+00:00
        updatedAt: 2025-06-29 07:47:39.370000+00:00
        emailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
        campaignGroupId: clg7n5p3q1r9s7t5u3v1w9y7
        mailingListId: clm2k8j4h6g0f8d6s4a2b0z8
        audienceSegmentId: null
        audienceFilter: null
        scheduling:
          method: now
          timestamp: null
        emailMessageContentRevisionId: clrev1s10n2i3d4e5f6g7h8
    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/campaign-groups?cursor=clp9k2m4n6p8q0r2s4t6u8v0&perPage=20
        data:
        - id: clc4m6n8p0q2r4s6t8u0v2x4
          name: Spring announcement
          status: Draft
          createdAt: 2025-06-29 07:47:39.370000+00:00
          updatedAt: 2025-06-29 07:47:39.370000+00:00
          emailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
          campaignGroupId: clg7n5p3q1r9s7t5u3v1w9y7
          mailingListId: clm2k8j4h6g0f8d6s4a2b0z8
          audienceSegmentId: null
          audienceFilter: null
          scheduling:
            method: now
            timestamp: null
    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
    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
    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
    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
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer