listmonk Transactional API

Send arbitrary transactional messages (welcome emails, order confirmations, password resets) to one or more subscribers through a preconfigured transactional template, with custom data, headers, attachments, and messenger selection.

OpenAPI Specification

listmonk-openapi.yml Raw ↑
openapi: 3.0.1
info:
  title: listmonk API
  description: >-
    REST API for listmonk, the free and open-source, self-hosted newsletter and
    mailing-list manager. All endpoints are served by a self-hosted listmonk
    instance under the /api path and are secured with HTTP Basic auth using an
    API user and token (or an equivalent `Authorization: token api_user:token`
    header). There is no hosted SaaS; replace the server host with your own
    instance.
  termsOfService: https://listmonk.app
  contact:
    name: listmonk
    url: https://listmonk.app/docs/apis/apis/
  license:
    name: AGPL-3.0
    url: https://github.com/knadh/listmonk/blob/master/LICENSE
  version: '4.1'
servers:
  - url: http://localhost:9000/api
    description: Default local self-hosted instance
  - url: '{host}/api'
    description: Self-hosted instance
    variables:
      host:
        default: http://localhost:9000
        description: Base URL of your listmonk instance
security:
  - BasicAuth: []
  - TokenAuth: []
tags:
  - name: Subscribers
  - name: Lists
  - name: Campaigns
  - name: Templates
  - name: Media
  - name: Transactional
  - name: Import
  - name: Bounces
paths:
  /subscribers:
    get:
      operationId: getSubscribers
      tags: [Subscribers]
      summary: Query and retrieve subscribers.
      parameters:
        - { name: query, in: query, schema: { type: string }, description: "SQL expression to filter subscribers, e.g. subscribers.name LIKE '%john%'." }
        - { name: list_id, in: query, schema: { type: array, items: { type: integer } } }
        - { name: page, in: query, schema: { type: integer } }
        - { name: per_page, in: query, schema: { type: integer } }
      responses:
        '200':
          description: A paginated list of subscribers.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/SubscribersResponse' }
    post:
      operationId: createSubscriber
      tags: [Subscribers]
      summary: Create a new subscriber.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/SubscriberRequest' }
      responses:
        '200':
          description: The created subscriber.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/SubscriberResponse' }
    delete:
      operationId: deleteSubscribers
      tags: [Subscribers]
      summary: Delete multiple subscribers by ID.
      parameters:
        - { name: id, in: query, schema: { type: array, items: { type: integer } } }
      responses:
        '200': { description: Deletion result. }
  /subscribers/{subscriber_id}:
    parameters:
      - { name: subscriber_id, in: path, required: true, schema: { type: integer } }
    get:
      operationId: getSubscriber
      tags: [Subscribers]
      summary: Retrieve a specific subscriber.
      responses:
        '200':
          description: The subscriber.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/SubscriberResponse' }
    put:
      operationId: updateSubscriber
      tags: [Subscribers]
      summary: Update a specific subscriber.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/SubscriberRequest' }
      responses:
        '200':
          description: The updated subscriber.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/SubscriberResponse' }
    delete:
      operationId: deleteSubscriber
      tags: [Subscribers]
      summary: Delete a specific subscriber.
      responses:
        '200': { description: Deletion result. }
  /subscribers/{subscriber_id}/optin:
    post:
      operationId: sendSubscriberOptin
      tags: [Subscribers]
      summary: Send an opt-in confirmation email to a subscriber.
      parameters:
        - { name: subscriber_id, in: path, required: true, schema: { type: integer } }
      responses:
        '200': { description: Opt-in email queued. }
  /subscribers/{subscriber_id}/export:
    get:
      operationId: exportSubscriber
      tags: [Subscribers]
      summary: Export a subscriber's data.
      parameters:
        - { name: subscriber_id, in: path, required: true, schema: { type: integer } }
      responses:
        '200': { description: Exported subscriber data. }
  /subscribers/lists:
    put:
      operationId: manageSubscriberLists
      tags: [Subscribers]
      summary: Add, remove, or unsubscribe subscribers from lists.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/SubscriberListsRequest' }
      responses:
        '200': { description: List membership updated. }
  /subscribers/query/lists:
    put:
      operationId: manageSubscriberListsByQuery
      tags: [Subscribers]
      summary: Add, remove, or unsubscribe subscribers from lists by SQL query.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/SubscriberListsRequest' }
      responses:
        '200': { description: List membership updated. }
  /subscribers/{subscriber_id}/blocklist:
    put:
      operationId: blocklistSubscriber
      tags: [Subscribers]
      summary: Blocklist a single subscriber.
      parameters:
        - { name: subscriber_id, in: path, required: true, schema: { type: integer } }
      responses:
        '200': { description: Subscriber blocklisted. }
  /subscribers/blocklist:
    put:
      operationId: blocklistSubscribers
      tags: [Subscribers]
      summary: Blocklist multiple subscribers by ID.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids: { type: array, items: { type: integer } }
      responses:
        '200': { description: Subscribers blocklisted. }
  /subscribers/query/blocklist:
    put:
      operationId: blocklistSubscribersByQuery
      tags: [Subscribers]
      summary: Blocklist subscribers matching a SQL expression.
      responses:
        '200': { description: Subscribers blocklisted. }
  /subscribers/query/delete:
    post:
      operationId: deleteSubscribersByQuery
      tags: [Subscribers]
      summary: Delete subscribers matching a SQL expression.
      responses:
        '200': { description: Subscribers deleted. }
  /lists:
    get:
      operationId: getLists
      tags: [Lists]
      summary: Retrieve all lists.
      parameters:
        - { name: query, in: query, schema: { type: string } }
        - { name: page, in: query, schema: { type: integer } }
        - { name: per_page, in: query, schema: { type: integer } }
      responses:
        '200':
          description: A paginated list of lists.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ListsResponse' }
    post:
      operationId: createList
      tags: [Lists]
      summary: Create a new list.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/ListRequest' }
      responses:
        '200':
          description: The created list.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ListResponse' }
    delete:
      operationId: deleteLists
      tags: [Lists]
      summary: Delete multiple lists by ID.
      parameters:
        - { name: id, in: query, schema: { type: array, items: { type: integer } } }
      responses:
        '200': { description: Deletion result. }
  /lists/{list_id}:
    parameters:
      - { name: list_id, in: path, required: true, schema: { type: integer } }
    get:
      operationId: getList
      tags: [Lists]
      summary: Retrieve a specific list.
      responses:
        '200':
          description: The list.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ListResponse' }
    put:
      operationId: updateList
      tags: [Lists]
      summary: Update an existing list.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/ListRequest' }
      responses:
        '200':
          description: The updated list.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ListResponse' }
    delete:
      operationId: deleteList
      tags: [Lists]
      summary: Delete a specific list.
      responses:
        '200': { description: Deletion result. }
  /public/lists:
    get:
      operationId: getPublicLists
      tags: [Lists]
      summary: Retrieve public lists (unauthenticated, for subscription forms).
      security: []
      responses:
        '200': { description: Public lists. }
  /campaigns:
    get:
      operationId: getCampaigns
      tags: [Campaigns]
      summary: Retrieve all campaigns.
      parameters:
        - { name: query, in: query, schema: { type: string } }
        - { name: status, in: query, schema: { type: array, items: { type: string } } }
        - { name: page, in: query, schema: { type: integer } }
        - { name: per_page, in: query, schema: { type: integer } }
      responses:
        '200':
          description: A paginated list of campaigns.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CampaignsResponse' }
    post:
      operationId: createCampaign
      tags: [Campaigns]
      summary: Create a new campaign.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CampaignRequest' }
      responses:
        '200':
          description: The created campaign.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CampaignResponse' }
    delete:
      operationId: deleteCampaigns
      tags: [Campaigns]
      summary: Delete multiple campaigns.
      responses:
        '200': { description: Deletion result. }
  /campaigns/{campaign_id}:
    parameters:
      - { name: campaign_id, in: path, required: true, schema: { type: integer } }
    get:
      operationId: getCampaign
      tags: [Campaigns]
      summary: Retrieve a specific campaign.
      responses:
        '200':
          description: The campaign.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CampaignResponse' }
    put:
      operationId: updateCampaign
      tags: [Campaigns]
      summary: Update a campaign.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CampaignRequest' }
      responses:
        '200':
          description: The updated campaign.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CampaignResponse' }
    delete:
      operationId: deleteCampaign
      tags: [Campaigns]
      summary: Delete an individual campaign.
      responses:
        '200': { description: Deletion result. }
  /campaigns/{campaign_id}/preview:
    get:
      operationId: previewCampaign
      tags: [Campaigns]
      summary: Retrieve an HTML preview of a campaign.
      parameters:
        - { name: campaign_id, in: path, required: true, schema: { type: integer } }
      responses:
        '200': { description: Rendered campaign HTML. }
  /campaigns/{campaign_id}/test:
    post:
      operationId: testCampaign
      tags: [Campaigns]
      summary: Send a test of the campaign to arbitrary subscribers.
      parameters:
        - { name: campaign_id, in: path, required: true, schema: { type: integer } }
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                subscribers: { type: array, items: { type: string }, description: List of test recipient emails. }
      responses:
        '200': { description: Test message queued. }
  /campaigns/{campaign_id}/status:
    put:
      operationId: updateCampaignStatus
      tags: [Campaigns]
      summary: Change the status of a campaign (running, paused, cancelled, scheduled).
      parameters:
        - { name: campaign_id, in: path, required: true, schema: { type: integer } }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                status: { type: string, enum: [scheduled, running, paused, cancelled, finished] }
      responses:
        '200': { description: Status updated. }
  /campaigns/{campaign_id}/archive:
    put:
      operationId: archiveCampaign
      tags: [Campaigns]
      summary: Publish or update a campaign in the public archive.
      parameters:
        - { name: campaign_id, in: path, required: true, schema: { type: integer } }
      responses:
        '200': { description: Archive settings updated. }
  /campaigns/running/stats:
    get:
      operationId: getRunningCampaignStats
      tags: [Campaigns]
      summary: Retrieve stats of running campaigns.
      parameters:
        - { name: campaign_id, in: query, schema: { type: array, items: { type: integer } } }
      responses:
        '200': { description: Running campaign stats. }
  /campaigns/analytics/{type}:
    get:
      operationId: getCampaignAnalytics
      tags: [Campaigns]
      summary: Retrieve view, click, link, or bounce counts for campaigns.
      parameters:
        - { name: type, in: path, required: true, schema: { type: string, enum: [views, clicks, links, bounces] } }
        - { name: id, in: query, schema: { type: array, items: { type: integer } } }
        - { name: from, in: query, schema: { type: string, format: date } }
        - { name: to, in: query, schema: { type: string, format: date } }
      responses:
        '200': { description: Campaign analytics. }
  /templates:
    get:
      operationId: getTemplates
      tags: [Templates]
      summary: Retrieve all templates.
      responses:
        '200':
          description: A list of templates.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/TemplatesResponse' }
    post:
      operationId: createTemplate
      tags: [Templates]
      summary: Create a template.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/TemplateRequest' }
      responses:
        '200':
          description: The created template.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/TemplateResponse' }
  /templates/{template_id}:
    parameters:
      - { name: template_id, in: path, required: true, schema: { type: integer } }
    get:
      operationId: getTemplate
      tags: [Templates]
      summary: Retrieve a template.
      responses:
        '200':
          description: The template.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/TemplateResponse' }
    put:
      operationId: updateTemplate
      tags: [Templates]
      summary: Update an existing template.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/TemplateRequest' }
      responses:
        '200':
          description: The updated template.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/TemplateResponse' }
    delete:
      operationId: deleteTemplate
      tags: [Templates]
      summary: Delete a template.
      responses:
        '200': { description: Deletion result. }
  /templates/{template_id}/preview:
    get:
      operationId: previewTemplate
      tags: [Templates]
      summary: Retrieve the rendered HTML preview of a template.
      parameters:
        - { name: template_id, in: path, required: true, schema: { type: integer } }
      responses:
        '200': { description: Rendered template HTML. }
  /templates/{template_id}/default:
    put:
      operationId: setDefaultTemplate
      tags: [Templates]
      summary: Set a template as the default.
      parameters:
        - { name: template_id, in: path, required: true, schema: { type: integer } }
      responses:
        '200': { description: Default template set. }
  /templates/preview:
    post:
      operationId: previewTemplateBody
      tags: [Templates]
      summary: Render and preview a template body without saving it.
      requestBody:
        content:
          application/json:
            schema: { $ref: '#/components/schemas/TemplateRequest' }
      responses:
        '200': { description: Rendered HTML. }
  /media:
    get:
      operationId: getMedia
      tags: [Media]
      summary: Retrieve uploaded media files.
      responses:
        '200':
          description: A list of media files.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/MediaResponse' }
    post:
      operationId: uploadMedia
      tags: [Media]
      summary: Upload a media file.
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file: { type: string, format: binary }
      responses:
        '200':
          description: The uploaded media file.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/MediaResponse' }
  /media/{media_id}:
    parameters:
      - { name: media_id, in: path, required: true, schema: { type: integer } }
    get:
      operationId: getMediaFile
      tags: [Media]
      summary: Retrieve a specific media file.
      responses:
        '200': { description: The media file. }
    delete:
      operationId: deleteMedia
      tags: [Media]
      summary: Delete an uploaded media file.
      responses:
        '200': { description: Deletion result. }
  /tx:
    post:
      operationId: sendTransactionalMessage
      tags: [Transactional]
      summary: Send a transactional message to one or more subscribers.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/TransactionalRequest' }
          multipart/form-data:
            schema:
              type: object
              properties:
                data: { type: string, description: JSON-encoded transactional payload. }
                file: { type: string, format: binary, description: Optional attachment. }
      responses:
        '200': { description: Message accepted and queued. }
  /import/subscribers:
    get:
      operationId: getImportStatus
      tags: [Import]
      summary: Retrieve the status of an ongoing import.
      responses:
        '200': { description: Import status. }
    post:
      operationId: importSubscribers
      tags: [Import]
      summary: Upload a CSV (optionally ZIP-compressed) file to import subscribers.
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                params: { type: string, description: JSON-encoded import params (mode, lists, delimiter, overwrite). }
                file: { type: string, format: binary }
      responses:
        '200': { description: Import started. }
    delete:
      operationId: stopImport
      tags: [Import]
      summary: Stop and delete an ongoing import.
      responses:
        '200': { description: Import stopped. }
  /import/subscribers/logs:
    get:
      operationId: getImportLogs
      tags: [Import]
      summary: Retrieve logs from an ongoing import.
      responses:
        '200': { description: Import logs. }
  /bounces:
    get:
      operationId: getBounces
      tags: [Bounces]
      summary: Retrieve bounce records.
      parameters:
        - { name: campaign_id, in: query, schema: { type: integer } }
        - { name: page, in: query, schema: { type: integer } }
        - { name: per_page, in: query, schema: { type: integer } }
      responses:
        '200':
          description: A paginated list of bounce records.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/BouncesResponse' }
    delete:
      operationId: deleteBounces
      tags: [Bounces]
      summary: Delete bounce records by ID or all.
      parameters:
        - { name: id, in: query, schema: { type: array, items: { type: integer } } }
        - { name: all, in: query, schema: { type: boolean } }
      responses:
        '200': { description: Deletion result. }
  /bounces/{bounce_id}:
    delete:
      operationId: deleteBounce
      tags: [Bounces]
      summary: Delete a single bounce record.
      parameters:
        - { name: bounce_id, in: path, required: true, schema: { type: integer } }
      responses:
        '200': { description: Deletion result. }
components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
      description: HTTP Basic auth using an API user name and token (api_user:token).
    TokenAuth:
      type: apiKey
      in: header
      name: Authorization
      description: "Authorization header in the form: token api_user:token."
  schemas:
    SubscriberRequest:
      type: object
      properties:
        email: { type: string, format: email }
        name: { type: string }
        status: { type: string, enum: [enabled, disabled, blocklisted] }
        lists: { type: array, items: { type: integer }, description: List IDs to subscribe to. }
        attribs: { type: object, additionalProperties: true, description: Arbitrary JSON attributes. }
        preconfirm_subscriptions: { type: boolean }
      required: [email]
    SubscriberResponse:
      type: object
      properties:
        data: { $ref: '#/components/schemas/Subscriber' }
    SubscribersResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            results: { type: array, items: { $ref: '#/components/schemas/Subscriber' } }
            total: { type: integer }
            page: { type: integer }
            per_page: { type: integer }
    Subscriber:
      type: object
      properties:
        id: { type: integer }
        uuid: { type: string }
        email: { type: string }
        name: { type: string }
        status: { type: string }
        attribs: { type: object, additionalProperties: true }
        lists: { type: array, items: { type: object } }
        created_at: { type: string, format: date-time }
        updated_at: { type: string, format: date-time }
    SubscriberListsRequest:
      type: object
      properties:
        ids: { type: array, items: { type: integer } }
        query: { type: string }
        action: { type: string, enum: [add, remove, unsubscribe] }
        target_list_ids: { type: array, items: { type: integer } }
        status: { type: string, enum: [unconfirmed, confirmed, unsubscribed] }
    ListRequest:
      type: object
      properties:
        name: { type: string }
        type: { type: string, enum: [public, private] }
        optin: { type: string, enum: [single, double] }
        tags: { type: array, items: { type: string } }
        description: { type: string }
      required: [name]
    ListResponse:
      type: object
      properties:
        data: { $ref: '#/components/schemas/List' }
    ListsResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            results: { type: array, items: { $ref: '#/components/schemas/List' } }
            total: { type: integer }
    List:
      type: object
      properties:
        id: { type: integer }
        uuid: { type: string }
        name: { type: string }
        type: { type: string }
        optin: { type: string }
        tags: { type: array, items: { type: string } }
        subscriber_count: { type: integer }
        created_at: { type: string, format: date-time }
    CampaignRequest:
      type: object
      properties:
        name: { type: string }
        subject: { type: string }
        lists: { type: array, items: { type: integer } }
        from_email: { type: string }
        type: { type: string, enum: [regular, optin] }
        content_type: { type: string, enum: [richtext, html, markdown, plain] }
        body: { type: string }
        template_id: { type: integer }
        messenger: { type: string }
        tags: { type: array, items: { type: string } }
        send_at: { type: string, format: date-time }
      required: [name, subject, lists]
    CampaignResponse:
      type: object
      properties:
        data: { $ref: '#/components/schemas/Campaign' }
    CampaignsResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            results: { type: array, items: { $ref: '#/components/schemas/Campaign' } }
            total: { type: integer }
    Campaign:
      type: object
      properties:
        id: { type: integer }
        uuid: { type: string }
        name: { type: string }
        subject: { type: string }
        status: { type: string }
        type: { type: string }
        content_type: { type: string }
        lists: { type: array, items: { type: object } }
        sent: { type: integer }
        to_send: { type: integer }
        created_at: { type: string, format: date-time }
    TemplateRequest:
      type: object
      properties:
        name: { type: string }
        type: { type: string, enum: [campaign, campaign_visual, tx] }
        subject: { type: string }
        body: { type: string }
      required: [name, type, body]
    TemplateResponse:
      type: object
      properties:
        data: { $ref: '#/components/schemas/Template' }
    TemplatesResponse:
      type: object
      properties:
        data: { type: array, items: { $ref: '#/components/schemas/Template' } }
    Template:
      type: object
      properties:
        id: { type: integer }
        name: { type: string }
        type: { type: string }
        subject: { type: string }
        body: { type: string }
        is_default: { type: boolean }
        created_at: { type: string, format: date-time }
    MediaResponse:
      type: object
      properties:
        data:
          oneOf:
            - { $ref: '#/components/schemas/Media' }
            - { type: array, items: { $ref: '#/components/schemas/Media' } }
    Media:
      type: object
      properties:
        id: { type: integer }
        uuid: { type: string }
        filename: { type: string }
        content_type: { type: string }
        url: { type: string }
        thumb_url: { type: string }
        created_at: { type: string, format: date-time }
    TransactionalRequest:
      type: object
      properties:
        subscriber_email: { type: string, format: email }
        subscriber_id: { type: integer }
        subscriber_emails: { type: array, items: { type: string } }
        subscriber_ids: { type: array, items: { type: integer } }
        template_id: { type: integer }
        subscriber_mode: { type: string, enum: [default, fallback, external] }
        from_email: { type: string }
        subject: { type: string }
        data: { type: object, additionalProperties: true, description: "Custom variables available in templates via {{ .Tx.Data.* }}." }
        headers: { type: array, items: { type: object, additionalProperties: { type: string } } }
        messenger: { type: string, default: email }
        content_type: { type: string, enum: [html, markdown, plain] }
        altbody: { type: string }
      required: [template_id]
    BouncesResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            results: { type: array, items: { $ref: '#/components/schemas/Bounce' } }
            total: { type: integer }
    Bounce:
      type: object
      properties:
        id: { type: integer }
        type: { type: string, enum: [hard, soft, complaint] }
        source: { type: string }
        subscriber_id: { type: integer }
        campaign_id: { type: integer }
        email: { type: string }
        created_at: { type: string, format: date-time }