A typed Python client for the Listmonk API built with Klarient.
Project description
Listmonk API Package
Library implements the Listmonk REST API via Python.
Requirements:
- Python 3.11+
- klarient
- requests
Installing the Package
You can install the API library using pip.
pip install klarient-listmonk
For local development from this folder, use an editable install.
python3 -m pip install -e .
Creating an API client object
from listmonk import ListMonkClient
if __name__ == '__main__':
client = ListMonkClient(
base_url="https://listmonk.example.com",
username="api-user",
access_token="api-token",
)
Endpoint Examples
Endpoint-focused examples are available under examples/.
examples/
bounces.py
campaigns.py
imports.py
lists.py
media.py
public.py
subscribers.py
templates.py
transactional.py
Copy examples/settings.example.json to examples/settings.json and add your Listmonk URL and API credentials to run
them locally.
Most scripts are read-only by default. Actions that create, update, delete, upload, blocklist, change defaults, or send
messages are guarded by settings flags such as create_test_data, delete_import, delete_uploaded_media,
delete_bounces, send_campaign_test, set_default_template, and delete_subscriber_bounces.
Resource Paths
The API is modeled as a resource tree. Each resource exposes its path and URL, which can be useful when learning or debugging the wrapper.
from listmonk import ListMonkClient
if __name__ == '__main__':
client = ListMonkClient(
base_url="https://listmonk.example.com",
username="api-user",
access_token="api-token",
)
print(client.lists.path)
# /api/lists
print(client.lists[1].path)
# /api/lists/1
print(client.templates[1].preview.path)
# /api/templates/1/preview
Querying Lists
from listmonk import ListMonkClient
from listmonk.common import PerPage
from listmonk.lists import ListQuery
if __name__ == '__main__':
client = ListMonkClient(
base_url="https://listmonk.example.com",
username="api-user",
access_token="api-token",
)
lists = client.lists.retrieve(ListQuery().with_per_page(PerPage.ALL))
print("Total Lists: {}".format(lists.record_count))
for item in lists:
print(item.id)
print(item.name)
Querying Subscribers
from listmonk import ListMonkClient
from listmonk.common import PerPage, SortOrder
from listmonk.subscribers import SubscriberOrderBy, SubscriberQuery
if __name__ == '__main__':
client = ListMonkClient(
base_url="https://listmonk.example.com",
username="api-user",
access_token="api-token",
)
query = (
SubscriberQuery()
.with_page(1)
.with_per_page(PerPage.ALL)
.with_order_by(SubscriberOrderBy.NAME)
.with_order(SortOrder.ASC)
)
subscribers = client.subscribers.retrieve(query)
print("Total Subscribers: {}".format(subscribers.record_count))
for subscriber in subscribers:
print(subscriber.id)
print(subscriber.email)
print(subscriber.name)
Subscriber SQL Query
Listmonk exposes SQL filtering on GET /api/subscribers. The wrapper models this as
client.subscribers.sql_query.
from listmonk import ListMonkClient
from listmonk.common import PerPage
from listmonk.subscribers import SubscriberSQLQuery
if __name__ == '__main__':
client = ListMonkClient(
base_url="https://listmonk.example.com",
username="api-user",
access_token="api-token",
)
response = client.subscribers.sql_query.retrieve(
SubscriberSQLQuery()
.with_sql("subscribers.id > 0")
.with_per_page(PerPage.ALL)
)
print("SQL Results: {}".format(response.record_count))
This requires the subscribers:sql_query permission. Listmonk documents that permission as powerful because it can
bypass individual list and subscriber permission boundaries, even though the query is read-only.
Previewing Templates
from listmonk import ListMonkClient
from listmonk.templates import TemplatePreviewRender, TemplateType
if __name__ == '__main__':
client = ListMonkClient(
base_url="https://listmonk.example.com",
username="api-user",
access_token="api-token",
)
existing = client.templates[1].preview.retrieve()
print(existing.data)
html = """
<!doctype html>
<html>
<body>
{{ template "content" . }}
{{ TrackView }}
</body>
</html>
""".strip()
preview = client.templates.preview.render(
TemplatePreviewRender(
type=TemplateType.CAMPAIGN,
body=html,
)
)
print(preview.data)
Listmonk expects POST /api/templates/preview to be form encoded, even though template create and update use JSON. The
wrapper hides that detail behind TemplatePreviewRender.
Uploading Media
from listmonk import ListMonkClient
from listmonk.media import MediaUpload
if __name__ == '__main__':
client = ListMonkClient(
base_url="https://listmonk.example.com",
username="api-user",
access_token="api-token",
)
uploaded = client.media.upload(MediaUpload.from_file("logo.png"))
print(uploaded.data.id)
print(uploaded.data.filename)
Sending Transactional Messages
from listmonk import ListMonkClient
from listmonk.transactional import (
TransactionalContentType,
TransactionalMessage,
TransactionalSubscriberMode,
)
if __name__ == '__main__':
client = ListMonkClient(
base_url="https://listmonk.example.com",
username="api-user",
access_token="api-token",
)
message = (
TransactionalMessage()
.with_template(1)
.with_subscriber_mode(TransactionalSubscriberMode.EXTERNAL)
.add_subscriber_email("user@example.com")
.with_content_type(TransactionalContentType.HTML)
.with_data("name", "Jane")
)
result = client.tx.send(message)
print(result.status)
Network Options
Network settings such as proxy, timeout, and SSL verification are configured with RequestsOptions.
from klarient import RequestsOptions, RequestsTimeout
from listmonk import ListMonkClient
if __name__ == '__main__':
client = ListMonkClient(
base_url="https://listmonk.example.com",
username="api-user",
access_token="api-token",
options=RequestsOptions(
timeout=RequestsTimeout(connect=10, read=120),
proxy="http://proxy.example.com:8080",
verify_ssl=True,
),
)
lists = client.lists.retrieve()
print(lists.status)
Proxy Support
A single proxy URL is used for both HTTP and HTTPS requests.
SOCKS5 proxy example:
from klarient import RequestsOptions
from listmonk import ListMonkClient
if __name__ == '__main__':
client = ListMonkClient(
base_url="https://listmonk.example.com",
username="api-user",
access_token="api-token",
options=RequestsOptions(
proxy="socks5h://proxyuser:proxypass@proxy.example.com:8128",
),
)
HTTP proxy example:
from klarient import RequestsOptions
from listmonk import ListMonkClient
if __name__ == '__main__':
client = ListMonkClient(
base_url="https://listmonk.example.com",
username="api-user",
access_token="api-token",
options=RequestsOptions(
proxy="http://proxyuser:proxypass@proxy.example.com:8080",
),
)
If your environment requires different proxies by scheme, pass a requests-style mapping:
from klarient import RequestsOptions
from listmonk import ListMonkClient
if __name__ == '__main__':
client = ListMonkClient(
base_url="https://listmonk.example.com",
username="api-user",
access_token="api-token",
options=RequestsOptions(
proxy={
"http": "http://proxy.example.com:8080",
"https": "http://secure-proxy.example.com:8080",
},
),
)
If your environment already uses standard proxy variables, those can also be used.
export HTTP_PROXY="http://proxy.example.com:8080"
export HTTPS_PROXY="http://proxy.example.com:8080"
HTTP Timeout Settings
from klarient import RequestsOptions, RequestsTimeout
from listmonk import ListMonkClient
if __name__ == '__main__':
client = ListMonkClient(
base_url="https://listmonk.example.com",
username="api-user",
access_token="api-token",
options=RequestsOptions(timeout=RequestsTimeout(connect=10, read=120)),
)
Endpoint Coverage
The wrapper models the documented Listmonk API areas:
- Bounces
- Campaigns
- Imports
- Lists
- Media
- Public list and subscription endpoints
- Subscribers
- Templates
- Transactional messages
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file klarient_listmonk-0.2.0.tar.gz.
File metadata
- Download URL: klarient_listmonk-0.2.0.tar.gz
- Upload date:
- Size: 39.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b9dc7f27da46e32c2ee2da1c9827a5eda49bb2202377e5837ff5884d73036c7
|
|
| MD5 |
5be71c89363b452929c76501a22c618c
|
|
| BLAKE2b-256 |
e8a0bda72f1750d11303bd57e66350ff370bbf474da46d18320a1e9d6ebf7170
|
Provenance
The following attestation bundles were made for klarient_listmonk-0.2.0.tar.gz:
Publisher:
python-publish.yml on ludvikjerabek/klarient-listmonk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
klarient_listmonk-0.2.0.tar.gz -
Subject digest:
3b9dc7f27da46e32c2ee2da1c9827a5eda49bb2202377e5837ff5884d73036c7 - Sigstore transparency entry: 2048434294
- Sigstore integration time:
-
Permalink:
ludvikjerabek/klarient-listmonk@d166b732d8ac0a439090ce346d0ec495cbb7fd16 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/ludvikjerabek
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@d166b732d8ac0a439090ce346d0ec495cbb7fd16 -
Trigger Event:
release
-
Statement type:
File details
Details for the file klarient_listmonk-0.2.0-py3-none-any.whl.
File metadata
- Download URL: klarient_listmonk-0.2.0-py3-none-any.whl
- Upload date:
- Size: 42.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c31d23f9cec23eb0389247ca9a94b958adfb9437bc885fd4ca1907ed1380dc4c
|
|
| MD5 |
40de8e28ec8a6d5409ca86a24ea1f235
|
|
| BLAKE2b-256 |
6ef661cb312493dd22abd050015c9d90c8e58d763e89c56f8e71b0659425afe2
|
Provenance
The following attestation bundles were made for klarient_listmonk-0.2.0-py3-none-any.whl:
Publisher:
python-publish.yml on ludvikjerabek/klarient-listmonk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
klarient_listmonk-0.2.0-py3-none-any.whl -
Subject digest:
c31d23f9cec23eb0389247ca9a94b958adfb9437bc885fd4ca1907ed1380dc4c - Sigstore transparency entry: 2048434306
- Sigstore integration time:
-
Permalink:
ludvikjerabek/klarient-listmonk@d166b732d8ac0a439090ce346d0ec495cbb7fd16 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/ludvikjerabek
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@d166b732d8ac0a439090ce346d0ec495cbb7fd16 -
Trigger Event:
release
-
Statement type: