zulipInteract with Zulip chat platform via REST API and Python client. Use when you need to read messages from streams/topics, send messages to channels or users,...
Install via ClawdBot CLI:
clawdbot install suky57/zulipInteract with Zulip chat platform for team communication.
pip install zulip
Create ~/.config/zulip/zuliprc:
[api]
email=bot@example.zulipchat.com
key=YOUR_API_KEY_HERE
site=https://example.zulipchat.com
Get credentials from Zulip admin panel (Settings → Bots).
python scripts/zulip_client.py streams
The scripts/zulip_client.py provides common operations:
List streams:
python scripts/zulip_client.py streams
python scripts/zulip_client.py streams --json
Read messages:
# Recent stream messages (by name)
python scripts/zulip_client.py messages --stream "General" --num 10
# By stream ID (more reliable, use 'streams' to find IDs)
python scripts/zulip_client.py messages --stream-id 42 --num 10
# Specific topic
python scripts/zulip_client.py messages --stream "General" --topic "Updates"
# Private messages
python scripts/zulip_client.py messages --type private --num 5
# Mentions
python scripts/zulip_client.py messages --type mentioned
Note: Stream names may have descriptions that look like part of the name. Use --stream-id for unambiguous identification.
Send messages:
# To stream
python scripts/zulip_client.py send --type stream --to "General" --topic "Updates" --content "Hello!"
# Private message (user_id)
python scripts/zulip_client.py send --type private --to 123 --content "Hi there"
List users:
python scripts/zulip_client.py users
python scripts/zulip_client.py users --json
import zulip
client = zulip.Client(config_file="~/.config/zulip/zuliprc")
# Read messages
result = client.get_messages({
"anchor": "newest",
"num_before": 10,
"num_after": 0,
"narrow": [{"operator": "stream", "operand": "General"}]
})
# Send to stream
client.send_message({
"type": "stream",
"to": "General",
"topic": "Updates",
"content": "Message text"
})
# Send DM
client.send_message({
"type": "private",
"to": [user_id],
"content": "Private message"
})
# List streams
curl -u "bot@example.com:KEY" https://example.zulipchat.com/api/v1/streams
# Get messages
curl -u "bot@example.com:KEY" -G \
"https://example.zulipchat.com/api/v1/messages" \
--data-urlencode 'anchor=newest' \
--data-urlencode 'num_before=20' \
--data-urlencode 'num_after=0' \
--data-urlencode 'narrow=[{"operator":"stream","operand":"General"}]'
# Send message
curl -X POST "https://example.zulipchat.com/api/v1/messages" \
-u "bot@example.com:KEY" \
--data-urlencode 'type=stream' \
--data-urlencode 'to=General' \
--data-urlencode 'topic=Updates' \
--data-urlencode 'content=Hello!'
def get_latest_messages(client, stream_name, last_seen_id=None):
narrow = [{"operator": "stream", "operand": stream_name}]
if last_seen_id:
# Get only messages after last seen
request = {
"anchor": last_seen_id,
"num_before": 0,
"num_after": 100,
"narrow": narrow
}
else:
# Get recent messages
request = {
"anchor": "newest",
"num_before": 20,
"num_after": 0,
"narrow": narrow
}
result = client.get_messages(request)
return result["messages"]
def reply_to_message(client, original_message, reply_text):
"""Reply in the same stream/topic as original message."""
client.send_message({
"type": "stream",
"to": original_message["display_recipient"],
"topic": original_message["subject"],
"content": reply_text
})
def search_messages(client, keyword, stream=None):
narrow = [{"operator": "search", "operand": keyword}]
if stream:
narrow.append({"operator": "stream", "operand": stream})
result = client.get_messages({
"anchor": "newest",
"num_before": 50,
"num_after": 0,
"narrow": narrow
})
return result["messages"]
def get_user_id(client, email):
"""Find user_id by email address."""
result = client.get_members()
for user in result["members"]:
if user["email"] == email:
return user["user_id"]
return None
Zulip uses Markdown:
texttext code ` `language\ncode\n` > quoted text@Full Name#stream-nametextwith open("file.pdf", "rb") as f:
result = client.upload_file(f)
file_url = result["uri"]
# Share in message
client.send_message({
"type": "stream",
"to": "General",
"topic": "Files",
"content": f"Check out [this file]({file_url})"
})
# Add reaction
client.add_reaction({
"message_id": 123,
"emoji_name": "thumbs_up"
})
# Remove reaction
client.remove_reaction({
"message_id": 123,
"emoji_name": "thumbs_up"
})
See references/api-quick-reference.md for complete API documentation, endpoints, and examples.
Config file not found:
~/.config/zulip/zuliprc exists with correct formatAuthentication failed:
Empty messages array:
client.get_subscriptions() to check subscriptionsRate limit errors:
Retry-After header on 429 responsesGenerated Mar 1, 2026
Automate sending daily stand-up summaries, project updates, or company-wide announcements to specific Zulip streams. This ensures timely communication across distributed teams, reducing manual effort and keeping everyone aligned with real-time notifications.
Monitor a dedicated Zulip stream for customer inquiries or support tickets, automatically parsing new messages to trigger responses or escalate issues. This streamlines support workflows by integrating chat-based requests into existing ticketing systems for faster resolution.
Use Zulip to receive and manage alerts from monitoring tools like Prometheus or Datadog, posting incidents to specific topics for team collaboration. Automate responses to acknowledge alerts, assign tasks, and log resolutions, improving incident response times.
Facilitate communication in online courses by automating message distribution to Zulip streams for assignments, announcements, and student queries. This helps instructors manage large cohorts by sending reminders and aggregating feedback efficiently.
Track marketing campaign discussions in Zulip by reading messages from relevant streams to gather team feedback and metrics. Automate sending updates on campaign performance or scheduling posts, enabling real-time adjustments and collaboration.
Offer a subscription-based service that integrates Zulip with other business tools like CRM or project management software, automating data sync and notifications. Revenue is generated through monthly fees based on usage tiers and premium features like advanced analytics.
Develop and sell custom AI-powered chatbots for Zulip that handle tasks such as answering FAQs, scheduling meetings, or generating reports. Revenue comes from one-time development fees and ongoing maintenance contracts, with pricing scaled to complexity.
Provide training sessions and consulting services to help organizations optimize their use of Zulip through automation and integration workflows. Revenue is earned via hourly rates for consulting and packaged training programs for teams.
💬 Integration Tip
Start by testing the helper script for basic operations like sending messages, then gradually integrate Python client functions into existing workflows for automation.
iMessage/SMS CLI for listing chats, history, watch, and sending.
Use when you need to control Discord from Clawdbot via the discord tool: send messages, react, post or upload stickers, upload emojis, run polls, manage threads/pins/search, fetch permissions or member/role/channel info, or handle moderation actions in Discord DMs or channels.
Use when you need to control Slack from Clawdbot via the slack tool, including reacting to messages or pinning/unpinning items in Slack channels or DMs.
Send WhatsApp messages to other people or search/sync WhatsApp history via the wacli CLI (not for normal user chats).
Build or update the BlueBubbles external channel plugin for Clawdbot (extension package, REST send/probe, webhook inbound).
OpenClaw skill for designing Telegram Bot API workflows and command-driven conversations using direct HTTPS requests (no SDKs).