Zulip

zulip.com
Zulip

Open source team chat organized around topic-based threading, which keeps busy conversations easier to follow than channel-only tools. Can be self-hosted, or used as a paid cloud service. The threading model takes some getting used to.

Open Source

Zulip Source Code

Author

zulip

Description

Zulip server and web application. Open-source team chat that helps teams stay productive and focused.

#apache#chat#collaboration#electron#foss#free#javascript#python#python3#react-native#slack#zulip

Homepage

https://zulip.com

License

Apache-2.0

Created

25 Sept 15

Last Updated

12 Jul 26

Latest version

shared-0.0.18

Primary Language

Python

Size

635,246 KB

Stars

25,479

Forks

9,947

Watchers

25,479

Language Usage

Language Usage

Star History

Star History

Top Contributors

Recent Commits

  • sandeep (23 Jun 26)

    compose: Prevent scroller arrows from blinking on button clicks. The formatting-bar scroller arrows hide when focus is within the formatting buttons.Clicking a button briefly puts focus inside the formatting bar before returning it to the textarea, which caused the arrows to blink off and back on during the click. Use :focus-visible instead of :focus-within so the hide rule only triggers for keyboard focus, not for click-induced focus. This generalizes to all clickable buttons in the bar (formatting, upload, etc.) without enumerating each class.

  • Aadyot1 (05 May 26)

    drafts: Add is_sending_saving to FormattedDraft. Pass the is_sending_saving flag through format_draft into the FormattedDraft type. The flag already exists on LocalStorageDraft; this makes it available to templates without changing any behavior. Fixes part of #32999.

  • Aadyot1 (10 May 26)

    drafts: Scope overlay selectors to drafts-tab-pane. Wrap the drafts list in a .drafts-tab-pane container and update the selectors that walk the drafts list. Add the min-height/height rules that keep the list scrolling correctly inside the new wrapper. This is a no-op refactor that prepares the overlay for an outbox tab living in a sibling .outbox-tab-pane container.

  • Alex Vandiver (25 Apr 26)

    import: Parallelize upload transfer across worker processes. Large realm imports can a long time serially uploading attachments to S3, one blocking HTTP round-trip at a time. Wrap the transfer loop in run_parallel_queue so workers can upload concurrently: each worker calls _init_upload_worker at startup to construct its own UploadDestination (a boto3 Bucket isn't fork-safe to share), and _execute_upload pulls it from a ContextVar per plan. Planning (which populates path_maps and resolves S3 metadata via ID_MAP and get_user_profile_by_id) stays serial in the main process, so downstream code sees a fully populated path_maps before it runs and workers don't need the import's in-memory state.

  • Alex Vandiver (22 Apr 26)

    import: Extract UploadPlan and UploadDestination in import_uploads. The per-record transfer loop branched on s3_uploads for each file, computing its S3-specific metadata inline and picking between key.upload_file and shutil.copy. Split that out so the destination-specific I/O lives on a small UploadDestination type, with one S3Destination and one LocalDestination subclass, and the loop just calls destination.execute(plan) for each record. build_plan always populates content_type and metadata; LocalDestination ignores them, which keeps UploadPlan self-consistent rather than having destination-dependent required fields. This is preparation for parallelizing the transfer phase; the only behavior change is that local-filesystem imports now do the same per-record get_user_profile_by_id lookup that S3 imports did before, which is cheap against Django's cache.

  • Aman Agrawal (06 Jul 26)

    thumbnail: Tolerate a missing content-type in missing_thumbnails. missing_thumbnails asserted that ImageAttachment.content_type is set. That holds for anything maybe_thumbnail creates, but not for rows migration 0660 backfilled from Attachment.content_type: uploads from before we recorded a content-type left it null, and a blank ?mimetype= parameter (before we guarded against it) left it empty. The assertion fires on two paths for such an image: the thumbnail queue worker (e.g. when `manage.py thumbnail` re-thumbnails old images), and the thumbnail-status endpoint in zerver/views/thumbnail.py, where an unhandled AssertionError becomes a user-facing 500. Use needs_transcoded_format, which judges a null or empty content-type as renderable inline (no transcoded format), exactly as get_transcoded_format does when serving. Sharing the helper keeps the generate and serve sides from disagreeing, which would otherwise produce a transcoded format that is never served, or vice versa. This stands on its own: it fixes the crash on every deployment, including self-hosted installs using local uploads, where no S3-side content-type backfill runs. Backfilling the underlying data is a separate change. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

  • Aman Agrawal (07 Jul 26)

    thumbnail: Rewrite needs_transcoded_format as a positive check. Convert the predicate from the negated "content_type is None or the bare type is inline" to the equivalent positive "has a content-type and the bare type is not inline". Besides reading better under the function's name, testing the content-type for truthiness first makes the treatment of a missing content-type explicit -- null or empty is judged inline -- rather than leaning on the non-obvious fact that bare_content_type("") is "text/plain", which is itself inline. No behavior change: for every content-type, including null and empty, the two forms agree. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

  • Aman Agrawal (07 Jul 26)

    thumbnail: Extract needs_transcoded_format helper. get_transcoded_format and missing_thumbnails both decide, from an image's content-type, whether it needs a transcoded web-safe format; the two must agree, or we generate a transcoded format that is never served, or skip one that is needed. Extract the check so they can share it. This commit is a pure refactor: the helper is the exact negation of the condition it replaces in get_transcoded_format, so behavior is unchanged. The next commit rewrites it into a clearer positive form, and a later commit puts missing_thumbnails on the shared helper. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

  • Sahil Batra (08 Jul 26)

    realm: Handle plan_type set to a paid plan without Customer. There can be cases where realm.plan_type is set to one of the paid plans but there are no CustomerPlan or Customer objects for that realm. This happens when support staff have manually set plan_type. We want to allow such realms to be able to configure two tier billing before they start paying, so this commit updates realm_eligible_for_non_workplace_pricing and realm_on_discounted_cloud_plan such that UI is enabled for the setting.

  • Shubham Padia (22 Jun 26)

    people: Match a typed user id exactly, not as a prefix. build_person_matcher lets a search query match a user by id, but compared with startsWith, so typing part of an id (e.g. "30") matched every user whose id begins with those digits. That floods results with unrelated users and collides with full names that start with digits, which can then be crowded out of a capped result list. User id lookup, added in 6c355f65324a (people: Allow user to lookup users using user id.), only needs to find the user whose id was typed in full, so compare against the whole id instead. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

  • Shubham Padia (16 Jun 26)

    search: Match people suggestions against typed text, not resolved id. Fixes https://chat.zulip.org/#narrow/channel/9-issues/topic/Search.20typeahead.20matches.20get.20slashed.20sometimes/with/2479827 When typing a person operator like `dm:`, `get_suggestions` canonicalizes the term, resolving a unique full name to that user's id (e.g. `dm:John` becomes `dm:50`). `make_people_getter` then queried people by that id instead of the typed text, collapsing the dropdown to the single exactly-named user `dm:joh` listed both "John" and "John Doe", but `dm:John` listed only "John". Now, we track the originally typed text on the term and use it for the people query, so suggestions match what the user typed. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

  • Gary Pendergast (07 Jul 26)

    migrations: Fix invalid deleted user "email" field values. 208c0c3 fixed `do_delete_user` to stop generating dummy users with invalid addresses of the form deleteduser@http://zulip.example.com, and `0439_fix_deleteduser_email` repaired the `delivery_email` field of users deleted before that fix. However, on realms whose `email_address_visibility` setting was "everyone", the `email` field held a copy of the same invalid address; such values still break realm import. Since `delivery_email` is guaranteed by migration `0439` to have already been repaired on every affected row, and the `email` field of the affected rows is by definition a copy of `delivery_email`, we restore the invariant by copying the repaired value. Fixes #28622.

  • sathwikshetty33 (06 Jun 26)

    webhooks/gitlab: Fix fixture names. During tests, `fixture_to_headers` generates the `HTTP_X_GITLAB_EVENT` header by splitting the fixture name on `__` and taking the left half. For Confidential events the header should start with `Confidential` but the fixture names `issue_hook__confidential_issue_*` and `note_hook__confidential_issue_note` produced headers without one. This was harmless in practice because Confidential Hooks and Normal Hooks are handled by the same event handler, so they rendered identical messages either way.

  • Aman Agrawal (02 Jul 26)

    echo: Guard failed-send handlers against a missing message. failed_message_success and message_send_error looked up the message with a non-null assertion (message_store.get(id)!) before writing failed_request, throwing "Cannot set properties of undefined (setting 'failed_request')" when the id is no longer in the store. This happens when a send appears to fail on the client but actually reached the server. The user clicks resend; if the original's get-events delivery arrives first, it reifies the local id to the real server id and re-keys the store. The resend's success handler then reifies the already-consumed local id to its own (duplicate) server id, which early-returns, so that id is never stored, and failed_message_success dereferenced the missing entry. The error handler is exposed the same way if the message is removed from the store while a resend is in flight. Guard both handlers: if the message is gone it has already been reconciled or removed, so there is nothing to mark. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

  • Aman Agrawal (02 Jul 26)

    echo: Export resend_message and test its send paths. resend_message drives the manual retry of a previously failed send. It was module-private and had no direct test coverage. Export it and add node tests for its success and error callbacks while the message is still in the store: the success path clears failed_request and the error path sets it. This is preparatory for the next commit, which guards those callbacks against a message that is no longer in the store. The tests added here pin the existing behavior when the message is present, so the guard does not silently regress it. No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

  • Rakshit Chauhan (24 Apr 26)

    compose: Keep scheduling popover open when choosing custom time. Previously, clicking inside the flatpickr calendar (e.g., on month or year) would hide the scheduling popover. Prevent this by ensuring interactions within flatpickr are not treated as outside clicks, so the popover remains open while selecting a custom time. Fixes: #35464

  • Pritesh Shetty (10 Jun 26)

    slack: Handle Slack Event API payloads without an event object. The Slack webhook view code read payload.get("event", {}) with an empty-dict default, but the next line immediately expected a key of "type" with a string value. When a payload arrived without an event object, this raised a ValidationError, which returned as errors in our logs. A well-formed Slack "event_callback" request always contains an event object. There are two documented event payloads where there is no event object. The "url_verification" payloads are already handled in the Slack webhook view code. The "app_rate_limited" payloads now return UnsupportedWebhookEventTypeError. Otherwise, if the event object is missing from the payload, then an AnomalousWebhookPayloadError is now returned.

  • Sahil Batra (06 Jul 26)

    settings: Fix height of creating indicator overlay. The "Creating channel..." and "Creating group..." overlay shown when creating channels and user groups respectively did not cover the available full height and thus did not look good. This commit fixes the CSS so that they cover the full height.

  • sandeep (14 Mar 26)

    right sidebar: Replace info banner with help icon. Previously, a large info banner was shown in the right side panel when no group was selected. This used extra space and made the layout crowded. Replace it with a small help icon next to the "User group settings" heading. The icon links to the user groups help page and is only shown when no group is selected. This is implemented by making the nothing-selected and group-selected title states symmetric. Previously the nothing-selected title was managed in two places: the heading text was hardcoded in `user_group_settings_overlay.hbs`, and `nothing_selected()` separately reset it via three imperative jQuery calls (`.text()` for the heading plus two `.hide()` calls for the deactivated icon and header actions). Now a new `nothing_selected_title.hbs` template owns the heading + help icon, and `nothing_selected()` renders it via a single `.html()` call. The deactivated icon and header actions no longer need explicit `.hide()` because the new template simply doesn't contain them; the HTML replacement removes them from the DOM. The hardcoded text in `user_group_settings_overlay.hbs` was emptied so the title string lives in only one place, matching how `render_selected_group_title()` already handles the group-selected state. Fixes part of #35556. Fixes #36118.

  • sandeep (14 Mar 26)

    left sidebar: Hide search and filter when no groups exist. Previously, the search box and filter dropdown were shown even when there were no user groups to filter, adding unnecessary UI elements. - Hide filter text box and dropdown per tab based on context: - "Your groups" tab: hide when user has no joined groups - "All groups" tab: hide when organization has no groups - "Roles" tab: hide only the dropdown, keep the search box - `is_filtered` / `is_searching` also check `#group_filter`'s visibility, so a stale search value doesn't trigger the "matching your filters" empty state when the filter is hidden. - `update_filter_widget_visibility(tab_name)` is invoked from `redraw_left_panel` before `update_empty_left_panel_message()`, so the empty-message logic sees current filter visibility. - The dropdown value resets only when the realm itself has one kind of group, so switching tabs preserves the user's selection. - Removes the now-unused `realm_has_deactivated_user_groups` function and its test.

  • Yogesh Shivaji (11 Mar 26)

    left sidebar: Convert user group links to buttons and improve empty states Previously, the user groups panel used links for actions that behaved like buttons, which was inconsistent with other UI components and not ideal for accessibility. - Convert links to proper buttons using action_button template - Add click handlers for "View all groups" and "Create user group" buttons - Show "View all groups" button in "Your groups" panel when user has no joined groups but organization has groups - Show "Create user group" button when organization has no groups and user has permission to create groups - Show correct empty state message based on tab and organization state - Separate 'margin-top' for groups and channels panels to avoid unintended side effects on channel settings - Button visibility is decided in TS, keeping the template focused on rendering. Fixes #35556.

  • Dhruva Kumar (06 Jul 26)

    management: Fix typo in FilteredManagementUtility docstring.

  • Evy Kassirer (30 Jun 26)

    typeahead: Sort users by direct message recency, not count. User typeahead and search suggestions previously ranked users by the number of direct messages you'd sent them. That count only tracked messages you sent and ignored how recent the conversation was. Rank by the recency of your latest direct message with each user instead, mirroring the mobile app, so people you've talked to recently surface first. For mentions in a channel this stays secondary to whether the user is subscribed to the channel. pm_conversations now maps each user to the message id of their most recent direct message conversation (1:1 or group, excluding yourself). This removes the now-unused recipient-count tracking and the is_partner helper, whose signal the recency map subsumes. Fixes #36488. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

  • Lauryn Menard (03 Jul 26)

    edit-history: Fix server message edit history schema. In commit c7ddd7884a, the server stopped sending the `content` and `rendered_content` fields for realms that had set the visibility policy for message edits to show message moves only. This updates the web app code so that the schema expected from the server has those fields marked as optional.

  • Anders Kaseorg (04 Jul 26)

    settings: Compute time zone UTC offsets on the client. Commit b0844109ca67f6e2385874620b74ad5c7f5b006f โ€œsettings: Show UTC offsets in timezone dropdownโ€ (#33609) baked a fixed UTC offset for each time zone into the generated timezones.json at installation time. UTC offsets are not constants: they change with daylight saving time (and tzdata updates), so the baked values were wrong for much of the year. The Python formatting was also incorrect for zones with negative fractional-hour offsets (divmod rounds toward negative infinity, so America/St_Johns at UTC-03:30 rendered as UTC-4:30). Revert the generated file to a plain list of names, and compute each offset in the web app when the picker is rendered, reusing the UTCยฑHH:MM formatting that message timestamp tooltips use. Computing all 446 offsets takes ~50ms the first time and ~1ms once @date-fns/tz has cached its formatters. Co-Authored-By: Claude Fable 5 <[email protected]> Signed-off-by: Anders Kaseorg <[email protected]>

  • Anders Kaseorg (04 Jul 26)

    timerender: Extract get_utc_offset_string helper. Co-Authored-By: Claude Fable 5 <[email protected]> Signed-off-by: Anders Kaseorg <[email protected]>

  • Anders Kaseorg (04 Jul 26)

    settings: Remove unused timezones template parameter. Commit 30479667ae1b0826231a88509a8fba257e67fcd5 โ€œprofile_settings: Convert timezone picker to dropdownwidgetโ€ (#35991) removed the {{#each timezones}} loop from profile_settings.hbs, leaving this template parameter unused. Co-Authored-By: Claude Fable 5 <[email protected]> Signed-off-by: Anders Kaseorg <[email protected]>

  • sandeep (30 Jun 26)

    compose: Keep formatting scroll arrows from overlapping the compose box. The formatting bar's scroll arrows only need to layer above the horizontally scrolling formatting buttons (z-index 0) they overlay, so their z-index of 5 was needlessly high; a value of 1 suffices. Lowering it also fixes a bug: in the message edit box, these arrows share a stacking context with the fixed #compose box (z-index 4). At z-index 5 they painted on top of the compose box when the edit box was resized to overlap it; at 1 (below #compose's 4) they now correctly sit behind it, with no reliance on DOM-order tiebreaks.

  • Anders Kaseorg (03 Jul 26)

    requirements: Upgrade Python requirements. Signed-off-by: Anders Kaseorg <[email protected]>

  • Anders Kaseorg (03 Jul 26)

    install-uv: Upgrade uv from 0.11.14 to 0.11.26. Signed-off-by: Anders Kaseorg <[email protected]>

Zulip Security

6.6/10

Repo Security Summary

Updated 06 Jul 26

  • Maintained 10/10
  • Security-Policy 10/10
  • Packaging N/A
  • Code-Review 9/10
  • CII-Best-Practices 0/10
  • Dangerous-Workflow 10/10
  • Token-Permissions 10/10
  • License 10/10
  • Signed-Releases 0/10
  • Binary-Artifacts 10/10
  • Branch-Protection 1/10
  • Pinned-Dependencies 0/10
  • Fuzzing 0/10
  • SAST 10/10

Security Advisories (32)

  • medium Patched

    CVE-2026-40300 Message edit history visible in "moves only" policy through /api/v1/messages/{id}/history

  • medium Unpatched CVSS 6.1

    CVE-2026-26058 Path Traversal in Import

  • high Patched CVSS 7.1

    CVE-2026-25741 Modification of Payment Method (Stripe Default Card) by Non-Billing Users

  • medium Unpatched CVSS 5.3

    CVE-2026-25742 Anonymous File Access After Disabling Spectator Access

  • low Patched

    CVE-2026-24050 Stored XSS in user profile modal

  • medium Patched CVSS 6.8

    CVE-2025-52559 XSS in digest preview URL

  • medium Patched

    CVE-2025-47930 Access control bypass for restrictions on creation of specific channel types

  • high Patched CVSS 8.2

    CVE-2025-31478 Authentication backend configuration bypass

  • low Patched CVSS 2.7

    CVE-2025-30368 Organization exports can be deleted by administrators of a different organization

  • low Patched CVSS 2.7

    CVE-2025-30369 Custom profile fields can be deleted by administrators of a different organization

  • medium Patched

    CVE-2025-27149 "Public data" administrative data exports can leak metadata for non-exported messages and client user agent strings

  • medium Patched CVSS 4.3

    CVE-2025-25195 Events can leak private channel names

  • medium Patched

    CVE-2024-56136 /api/v1/jwt/fetch_api_key endpoint can leak if an email address has an account

  • high Patched

    CVE-2024-27286 Moving messages from public to private streams may leave them accessible

  • medium Patched CVSS 4.3

    CVE-2024-21630 Non-admins can invite new users to streams they would not otherwise be able to add existing users to

  • medium Patched CVSS 4.3

    CVE-2023-47642 Invalid metadata access for formerly subscribed streams.

  • high Patched CVSS 8.2

    CVE-2023-33186 Cross-site scripting vulnerability in Zulip Server development branch via topic tooltip

  • medium Patched CVSS 4.3

    CVE-2023-32677 Users who can send invitations can add users to streams during invitation, even if they cannot add users to streams at other times

  • high Patched CVSS 7.5

    CVE-2023-28623 Unauthorized user can register an account in specific configurations involving LDAP and another external authentication backend

  • medium Patched CVSS 5.4

    CVE-2023-22735 User uploads proxied from S3 lack `Content-Security-Policy` headers, may be served with `Content-Disposition: inline`

  • medium Patched CVSS 6.5

    CVE-2023-32678 Insufficient authorization check for edition/deletion of messages and topics in private streams by former subscribers

  • medium Patched CVSS 4.8

    CVE-2022-41914 Non-constant-time SCIM token comparison in Zulip Server

  • medium Patched CVSS 4.3

    CVE-2022-36048 IP address leak via image proxy bypass in Zulip Server

  • medium Patched CVSS 5.4

    CVE-2022-31168 Insufficient authorization check for changing bot roles in Zulip Server

  • medium Patched CVSS 4.9

    CVE-2022-31134 Public data export contains attachments that are non-public

  • low Patched CVSS 2

    CVE-2022-31017 Zulip Server exposes edit events for old messages to new subscribers in protected-history streams

  • low Patched

    CVE-2022-24751 Race condition in user deactivation allows continued API access

  • medium Patched CVSS 4.6

    CVE-2022-23656 Cross-site scripting vulnerability in Zulip Server development branch via tooltip

  • high Patched CVSS 7.2

    CVE-2022-21706 Multi-use invitations can grant access to other organizations

  • high Patched CVSS 8.6

    CVE-2021-43799 RabbitMQ exposes ports with weak default secrets

  • medium Patched

    CVE-2021-43791 Ineffective expiration validation for invitation links

  • medium Patched CVSS 4.3

    CVE-2021-41115 Regular expression denial-of-service in linkifiers

Zulip Website

Website

Zulip โ€” organized team chat

Zulip is an organized team chat app for distributed teams of all sizes.

Redirects

Does not redirect

Security Checks

All 65 security checks passed

Server Details

  • IP Address 34.225.147.149
  • Hostname ec2-34-225-147-149.compute-1.amazonaws.com
  • Location Ashburn, Virginia, United States of America, NA
  • ISP Amazon Technologies Inc.
  • ASN AS16509

Associated Countries

  • US US
  • CA CA

Safety Score

Website marked as safe

100%

Blacklist Check

zulip.com was found on 0 blacklists

  • AntiSocial Blacklist
  • Artists Against 419
  • Badbitcoin
  • Bambenek Consulting
  • CERT Polska
  • CoinBlockerLists
  • CRDF
  • CryptoScamDB
  • EtherAddressLookup
  • EtherScamDB
  • Fake Website Buster
  • MetaMask EthPhishing
  • NABP Not Recommended Sites
  • OpenPhish
  • PetScams
  • PhishFeed
  • PhishFort
  • Phishing.Database
  • PhishStats
  • PhishTank
  • Phishunt
  • RPiList Not Serious
  • Scam.Directory
  • SecureReload Phishing List
  • Spam404
  • StopGunScams
  • Suspicious Hosting IP
  • ThreatFox
  • ThreatLog
  • TweetFeed
  • URLhaus
  • ViriBack C2 Tracker

Website Preview

Website preview

Zulip Android App

APK Info

De-Googled Compatibility

Native 4.00 / 4 1 ratings
microG 4.00 / 4 1 ratings

Tested on Android 15โ€“16 ยท Updated 17 May 26 ยท View on Plexus โ†’

Trackers

  • Sentry

Permissions

  • Access Network State
  • Access Wifi State
  • Internet
  • Post Notifications
  • Read External Storage
  • Vibrate
  • Wake Lock
  • Write External Storage

Zulip Reviews

More Team Collaboration

  • Privacy-focused messenger using the Matrix protocol. The Element client allows for group chat rooms, media sharing voice and video group calls.

  • An IRC-based solution is another option, being decentralized there is no point of failure, and it's easy to self-host. However it's important to keep security in mind while configuring your IRC instance and ensure that channels are properly encrypted - IRC tends to be better for open communications. There's a variety of clients to choose from - popular options include: The Longe (Web-based), HexChat (Linux), Pidgin (Linux), WeeChat (Linux, terminal-based), IceChat (Windows), XChat Aqua (MacOS), Palaver (iOS) and Revolution (Android).

  • Mattermost has an open source edition, which can be self-hosted. It makes a good Slack alternative, with native desktop, mobile and web apps and a wide variety of integrations.

  • Secure group communications, with the option to be used over Tor or I2P. Fast intuitive group and 1-to-1 chats with text and rich media using decentralized chat rooms, with a mail feature for delivering messages to offline contacts. A channels feature makes it possible for members of different teams to stay up-to-date with each other, and to share files. Also includes built-in forums, link aggregations, file sharing and voice and video calling. RetroShare is a bit more complex to use than some alternatives, and the UI is quite retro, so may not be appropriate for a non-technical team.

  • Easy-to-deploy, self-hosted team collaboration platform with stable, feature-rich cross-platform client apps. The UI is fast, good looking and intuitive, so very little technical experience is needed for users of the platform. Rocket.Chat's feature set is similar to Slack's, making it a good replacement for any team looking to have greater control over their data.

About the Data: Zulip

Change History

API

You can access Zulip's data programmatically via our API. Simply make a GET request to:

https://api.awesome-privacy.xyz/v1/services/zulip

The REST API is free, no-auth and CORS-enabled. To learn more, view the API Docs or read the API Usage Guide.

Share Zulip

Help your friends compare Team Collaboration, and pick privacy-respecting software and services.
Share Zulip and Awesome Privacy with your network!

View Team Collaboration (6)