Fix campaign/listmonk API shapes against confirmed source, not guesses

Read knadh/listmonk's actual Go source (cmd/campaigns.go, cmd/subscribers.go)
instead of relying on incomplete public docs. Two corrections: the media
attach field is "media" (plain IDs), not "media_ids" as originally guessed;
and there's a single query-based bulk list action
(PUT /api/subscribers/query/lists) that applies a segment_query server-side,
so resolveSegment no longer fetches subscriber IDs client-side before
bulk-adding them. Create-status-defaults-to-draft and the test-send
"subscribers" field are now confirmed rather than flagged TODO(verify).
This commit is contained in:
2026-07-10 08:37:07 -04:00
parent b16d2b6c5f
commit bcf8df5579
5 changed files with 109 additions and 166 deletions
+7 -9
View File
@@ -157,21 +157,19 @@ func resolveLists(lm *listmonk.Client, names []string) ([]int, error) {
// resolveSegment materializes a segment_query into list membership, since a
// listmonk campaign can only target whole list(s), not an arbitrary query
// directly (still an open, unmerged upstream feature request — see the
// plan's Open items). The list is a point-in-time snapshot: re-running sync
// re-evaluates the query and re-syncs membership, so a later push before
// send picks up newly-matching subscribers.
// plan's Open items). listmonk applies the query server-side in one call
// (QueryAddToList) — no subscriber IDs are ever fetched client-side. The
// list is a point-in-time snapshot: re-running sync re-evaluates the query
// and re-syncs membership, so a later push before send picks up
// newly-matching subscribers.
func resolveSegment(lm *listmonk.Client, slug, query string) (int, error) {
ids, err := lm.QuerySubscriberIDs(query)
if err != nil {
return 0, fmt.Errorf("segment_query: %w", err)
}
listName := "segment:" + slug
listID, err := lm.FindOrCreateListByName(listName)
if err != nil {
return 0, fmt.Errorf("segment list %q: %w", listName, err)
}
if err := lm.BulkAddToList(ids, listID); err != nil {
return 0, fmt.Errorf("segment list %q: %w", listName, err)
if err := lm.QueryAddToList(query, listID); err != nil {
return 0, fmt.Errorf("segment_query: %w", err)
}
return listID, nil
}