Project

listmonk

0.0
The project is in a healthy, maintained state
A resource-oriented Ruby client for listmonk's HTTP API.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 13.0
~> 4.0
~> 3.13
~> 1.0
~> 0.22
~> 3.0

Runtime

>= 2.0, < 3.0
 Project Readme

Listmonk

A resource-oriented Ruby client for the listmonk HTTP API.

Installation

Add the gem to your bundle:

bundle add listmonk

The gem requires Ruby 3.3 or newer.

Configuration

Listmonk supports Basic authentication and its Authorization: token header. Basic authentication is the default:

client = Listmonk::Client.new(
  base_url: "https://newsletter.example.com",
  username: ENV.fetch("LISTMONK_USERNAME"),
  token: ENV.fetch("LISTMONK_TOKEN")
)

Use token-header authentication when needed:

client = Listmonk.client(
  base_url: "https://newsletter.example.com/api",
  username: ENV.fetch("LISTMONK_USERNAME"),
  token: ENV.fetch("LISTMONK_TOKEN"),
  auth: :token,
  timeout: 30,
  open_timeout: 10
)

The client accepts a server root or an URL ending in /api. Credentials may be omitted for public endpoints.

Usage

Every method returns a Listmonk::Response. Use data for the API payload, or inspect status, headers, and body when needed.

response = client.subscribers.list(page: 1, per_page: 50, list_id: [1, 2])
subscribers = response.data.fetch("results")

subscriber = client.subscribers.create(
  email: "reader@example.com",
  name: "A Reader",
  lists: [1],
  attribs: {source: "website"}
).data

client.subscribers.update(subscriber.fetch("id"), name: "Reader")
client.subscribers.send_optin(subscriber.fetch("id"))

Campaigns and transactional messages:

campaign = client.campaigns.create(
  name: "July news",
  subject: "What's new",
  lists: [1],
  from_email: "News <news@example.com>",
  content_type: "html",
  messenger: "email",
  type: "regular"
).data

client.campaigns.create_content(campaign.fetch("id"), body: "<h1>Hello</h1>")
client.campaigns.start(campaign.fetch("id"))

client.transactional.deliver(
  template_id: 3,
  subscriber_email: "reader@example.com",
  data: {confirmation_url: "https://example.com/confirm"}
)

Subscriber imports and media uploads use multipart requests:

client.imports.create(
  file: "/tmp/subscribers.zip",
  params: {
    mode: "subscribe",
    subscription_status: "confirmed",
    lists: [1],
    overwrite: true
  }
)

client.media.upload(file: "/tmp/banner.png", content_type: "image/png")

Resources cover all operations in the published Swagger collection:

  • miscellaneous, settings, admin, and logs
  • subscribers, lists, imports, and bounces
  • campaigns, templates, media, and transactional
  • maintenance and public

For an undocumented or newly added endpoint, use the low-level request method:

client.request(:get, "new-endpoint", params: {page: 1})
client.request(:post, "new-endpoint", json: {enabled: true})

Errors

Non-successful responses raise typed exceptions. Every HTTP exception exposes status, body, and response.

begin
  client.lists.retrieve(999)
rescue Listmonk::NotFoundError => error
  warn "List not found: #{error.body.inspect}"
rescue Listmonk::RateLimitError
  # Retry with application-specific backoff.
end

Connection failures raise Listmonk::ConnectionError, timeouts raise Listmonk::TimeoutError, and malformed JSON raises Listmonk::ParseError.

Development

Install dependencies and run the complete verification task:

bin/setup
bundle exec rake

RSpec uses WebMock for request-level tests and SimpleCov for coverage.

Docker integration tests

Run the opt-in integration suite against an ephemeral Listmonk 6.1.0 and PostgreSQL 17 environment:

bundle exec rake integration

The task starts Docker Compose on 127.0.0.1:19000, creates a temporary API user, runs live list, subscriber, template, authentication, and health checks, then removes the containers and database volume. Override the defaults with LISTMONK_PORT or LISTMONK_IMAGE.

Normal bundle exec rake runs only the WebMock suite and does not require Docker.

Releasing

Publishing uses RubyGems trusted publishing, so no long-lived RubyGems API key is stored in GitHub.

Before the first release, create a pending trusted publisher in your RubyGems.org profile with:

  • Gem name: listmonk
  • Repository owner: polydice
  • Repository name: listmonk-ruby
  • Workflow filename: release.yml
  • Environment: release

To publish a version:

  1. Update lib/listmonk/version.rb and CHANGELOG.md.
  2. Run bundle exec rake, bundle exec rake integration, and bundle exec rbs validate.
  3. Run bundle exec rake build and inspect the generated package under pkg/.
  4. Commit the release and create a matching version tag, for example git tag v0.1.0.
  5. Push main and the tag. The Publish gem GitHub workflow validates that the tag matches Listmonk::VERSION and publishes the gem.

License

The gem is available under the terms of the MIT License.