@technomoron/listmonk-client
v1.0.6
Published
Minimal Listmonk API for managing subscriptions
Readme
Listmonk Client
Minimal TypeScript client for the Listmonk HTTP API with a small response wrapper and helpers for common flows (create subscribers, list members, bulk add, change email).
Interfaces (LMC*)
LMCConfigapiURL(string, required): base API URL.token(string, required): Basic auth token/password.user(string, required): Basic auth username.timeoutMS(number, optional): request timeout in milliseconds (default15000).debug(boolean, optional): enable request logging.listPageSize(number, optional): defaultper_pagefor paging.listCacheSeconds(number, optional): cache list metadata for this duration (seconds) to include list names in unsubscribe results and validate provided list ids.
LMCResponseData<T>success(boolean, required): indicates the request succeeded.code(number, required): HTTP status code returned by the API.message(string, required): human-readable status text.data(T | null, required): typed payload ornull.
LMCSubscriberAttribs- Record<string, JsonValue> (JSON-safe attributes).
LMCSubscriptionStatus"enabled" | "disabled" | "blocklisted" | "unconfirmed" | "bounced" | "unsubscribed"(also returned in membership data).
LMCSubscribeOptionspreconfirm(boolean, optional): preconfirm subscriptions (defaulttrue).status(LMCSubscriptionStatus, optional): override subscriber status.
LMCListMemberStatus"subscribed" | "unsubscribed" | "blocked".
LMCListVisibility"private" | "public"for list filtering.
LMCSubscriptionid(number, required): numeric list id.subscription_status(LMCSubscriptionStatus, optional): status of the subscriber on this list.
LMCSubscriberid(number, required): subscriber id.uuid(string, required): subscriber UUID.email(string, required): subscriber email address.name(string, required): subscriber display name.attribs(LMCSubscriberAttribs, required): custom attributes.status(string, required): global subscriber status (e.g., enabled, blocklisted).lists(array, optional):LMCSubscriptionorLMCListRecordentries.created_at(string, optional): created timestamp.updated_at(string, optional): updated timestamp.
LMCListRecordid(number, required): numeric list id.uuid(string, optional): list UUID.name(string, optional): display name.type(string, optional): list type (e.g., public/opt-in).tags(string[], optional): list tags.created_at(string, optional): list created timestamp.updated_at(string, optional): list updated timestamp.subscription_status(LMCSubscriptionStatus, optional): merged membership status when attached to a subscriber.
LMCSubscriberPageresults(LMCSubscriber[], required): page of subscribers.total(number, required): total matching subscribers for the query.per_page(number, required): page size used.page(number, required): current page number.query(string, optional): applied filter (when present).
LMCBulkSubscriptionemail(string, required): subscriber email.name(string, optional): display name.uid(string, optional): caller-defined unique id for deduplication.attribs(LMCSubscriberAttribs, optional): attributes;uidis mirrored when present.
LMCUseremail(string, required): subscriber email.name(string, optional): display name.uid(string, optional): caller-defined id; mirrored intoattribs.uid.attribs(LMCSubscriberAttribs, optional): attributes; merged on update.
LMCSyncUsersResultblocked(number): subscribers skipped due to blocklist.unsubscribed(number): subscribers skipped due to unsubscribed status.added(number): subscribers added/attached to the list.updated(number): subscribers whose data changed.
LMCSubscriptionSnapshotemail(string, required): processed email.lists(LMCSubscription[], optional): memberships observed.
LMCBulkAddResultcreated(LMCSubscriber[], required): subscribers created.added(LMCSubscriber[], required): existing subscribers attached.skippedBlocked(string[], required): emails skipped due to blocklist.skippedUnsubscribed(string[], required): emails skipped due to unsubscribed status.memberships(LMCSubscriptionSnapshot[], optional): membership snapshots.
LMCBulkAddErroremail(string, required): email that failed to process.message(string, required): failure message.code(number, optional): HTTP status or error code when available.
LMCSubscribeResultsubscriber(LMCSubscriber | null): subscriber returned by the API.added(boolean):truewhen the call added the subscriber to the list.alreadySubscribed(boolean):truewhen the subscriber was already on the list.created(boolean):truewhen a new subscriber record was created.
Installation
pnpm add @technomoron/listmonk-client
# or npm/yarn/pnpm equivalentUsage
import { ListMonkClient } from "@technomoron/listmonk-client";
const client = new ListMonkClient({
apiURL: "https://your-listmonk.example.com/api",
user: "admin",
token: "your-token",
});
// Example call
client.listAllLists().then((res) => {
if (res.success && res.data) {
console.log(
"Lists:",
res.data.map((l) => l.name),
);
}
});All methods return LMCResponse<T>:
/* eslint-disable @typescript-eslint/no-unused-vars */
type LMCResponse<T> = {
success: boolean;
code: number;
message: string;
data: T | null;
};
/* eslint-enable @typescript-eslint/no-unused-vars */Use response.isSuccess() as a type guard, or inspect success/data.
API
new ListMonkClient(config)
config: LMCConfig(see Interfaces)
Low-level helpers
client.get(path),client.post(path, body?),client.put(path, body?),client.delete(path, body?)- Return
LMCResponse<T>wrappers around Listmonk API calls.
client.listAllLists(visibility?)
Fetch every list with an optional visibility filter.
visibility:"public" | "private" | "all"(defaultall).- Returns
LMCResponse<LMCListRecord[]>.
client.getSubscriberById(id)
Fetch a subscriber by id. Returns LMCResponse<LMCSubscriber>.
client.getSubscriberByUuid(uuid)
Fetch a subscriber by uuid. Returns LMCResponse<LMCSubscriber>.
client.getSubscriberByEmail(email)
Fetch a subscriber by email. Returns LMCResponse<LMCSubscriber>.
client.getSubscriber(identifier)
Fetch a subscriber by id, uuid, or email.
identifier:{ id?: number; uuid?: string; email?: string }(one required)- Returns
LMCResponse<LMCSubscriber>.
client.syncUsersToList(listId, users)
Upsert subscribers into a list by uid, updating email/name/attribs when they
differ.
listId: target list id.users:LMCUser[](each entry must includeuid).- Returns
LMCResponse<LMCSyncUsersResult>with counts forblocked,unsubscribed,added,updated(added and updated can overlap when both occur for the same subscriber).
client.setSubscriptions(identifier, listIds, options?)
Set a subscriber's list memberships (opted-in) with optional pruning.
identifier:{ id?: number; uuid?: string; email?: string }(one required)listIds:number[]target lists to be subscribed to (preconfirmed).options?:{ removeOthers?: boolean }(falseby default). Whentrue, unsubscribe from lists not present inlistIds.- Returns
LMCResponse<{ subscriberId: number; lists: { listId: number; listName?: string; status: "Subscribed" | "Unsubscribed" | "Unchanged" | "Unknown List"; }[] }>(statusreflects actions taken; list names included when available from the cache/subscriber record).
client.updateUser(identifier, updates)
Update a subscriber by id, uuid, or email.
identifier:{ id?: number; uuid?: string; email?: string }(one required)updates:Partial<LMCUser>;uidis mirrored intoattribs.uidwhen set.options?:{ forceUidChange?: boolean }; whenuidis provided and an existingattribs.uidis present, the update is rejected unlessforceUidChangeistrue.- Returns
LMCResponse<LMCSubscriber>.
client.subscribe(listId, { email, name?, attribs? }, options?)
Create a subscriber (if it doesn't exist) and subscribe it to a list.
listId: numeric list id.attribs: arbitrary JSON-safe map to store alongside the subscriber.options:LMCSubscribeOptions(preconfirm,status).- Returns
LMCResponse<LMCSubscribeResult>;messageis"Successfully subscribed"when the list was updated,"Already subscribed"when no change was needed, orFailed to subscribe: ...when an error occurs. Existing unsubscribed members are re-attached (unless blocklisted).
client.unsubscribe(identifier, lists?)
Unsubscribe a subscriber from all lists or specific lists.
identifier:{ id?: number; uuid?: string; email?: string }(one required)lists:number | number[] | undefined(omit or[]to unsubscribe from all lists)- Returns
LMCResponse<{ subscriberId: number; lists: { listId: number; listName?: string; statusChanged: boolean; message: "Subscribed" | "Unsubscribed" | "Unknown List" }[] }>listsincludes list names whenlistCacheSecondsis configured and the cache is populated; falls back to ids when names are unavailable.statusChangedistruewhen the subscriber was on that list before the call. Unknown list ids are tolerated and reported withmessage: "Unknown List".
client.listMembersByStatus(listId, status, pagination?)
List subscribers on a list by status.
status:LMCListMemberStatuspagination:{ page?: number; perPage?: number }(defaultsperPagetolistPageSizefrom config)- Returns
LMCResponse<LMCSubscriberPage>.
client.addSubscribersToList(listId, entries, options?)
Bulk create/add subscribers.
entries: LMCBulkSubscriberInput[]where each entry is{ email: string; name?: string; attribs?: Record<string, JsonValue>; uid?: string }options:{ attachToList?: boolean }(defaulttrue)true: creates and attaches to the list.false: creates if missing, but does not attach to the list.
- Returns
LMCResponse<LMCBulkAddResult>with:created: LMCSubscriber[]added: LMCSubscriber[]skippedBlocked: string[]skippedUnsubscribed: string[]memberships?: { email: string; lists?: LMCSubscription[] }[](current lists seen for each processed email)errors?: { email: string; message: string; code?: number }[]when one or more entries fail (partial success returnssuccess: false,code: 207).
client.deleteSubscriber(id)
Delete a single subscriber by id. Returns LMCResponse<boolean>.
client.blockSubscriber(id)
Blocklist a subscriber by id. Returns LMCResponse<LMCSubscriber>.
client.unblockSubscriber(id)
Remove blocklist status for a subscriber by id. Returns
LMCResponse<LMCSubscriber>.
client.deleteSubscribers(ids)
Delete many subscribers. Returns LMCResponse<boolean>.
Debugging
Set debug: true in the client config to log all requests/headers and follow
API calls during tests or troubleshooting.
Example: WordPress user sync
scripts/wp-sync-example.mjs shows how to:
- Read WordPress users via Sequelize.
- Sync them to a Listmonk list by
uid/email/name (creates or updates). - Store the Listmonk subscriber id in a
listmonk_subscriber_idusermeta row.
Env vars expected: WP_DB_HOST, WP_DB_USER, WP_DB_PASSWORD, WP_DB_NAME,
WP_TABLE_PREFIX?, LISTMONK_URL, LISTMONK_USER, LISTMONK_TOKEN,
LISTMONK_LIST_ID.
