Skip to content

[CHA-5933] feat: support scheduled messages - #278

Open
nijeesh-stream wants to merge 4 commits into
mainfrom
feature/cha-5933-scheduled-messages
Open

nijeesh-stream wants to merge 4 commits into
mainfrom
feature/cha-5933-scheduled-messages

Conversation

@nijeesh-stream

Copy link
Copy Markdown
Contributor

TLDR

Backends can now schedule a chat message to be sent later, on behalf of any user, and then list, edit, cancel or send early those scheduled messages. Message.send(...).scheduledAt(date) stores the message instead of sending it; the new ScheduledMessage class covers the rest. Risk is low: the change is additive (one new optional request field, two new optional response fields, one new model and service). The backend endpoints are behind a per-app flag and not yet released, so merge after backend CHA-5924 ships.

Ticket

CHA-5933

CLA

  • I have signed the Stream CLA (required).
  • The code changes follow best practices
  • Code changes are tested (add some information if not applicable)

Description of the pull request

Backend endpoints are behind a per-app flag and not yet released; merge after backend CHA-5924 ships.

API surface

Call Endpoint
Message.send(type, id).scheduledAt(date) POST /channels/{type}/{id}/message with scheduled_at; response gains scheduled_message
ScheduledMessage.query().userId(..).filter(..).sort(..).limit(..).next(..) POST /scheduled_messages/query (user_id is required server-side; filter cid and status; only scheduled_at ascending; limit 1-100, default 20; cursor next)
ScheduledMessage.update(id).message(..).scheduledAt(..) PATCH /scheduled_messages/{id} (either or both)
ScheduledMessage.delete(id) DELETE /scheduled_messages/{id} (cancel, or remove a failed one)
ScheduledMessage.sendNow(id) POST /scheduled_messages/{id}/send_now
  • ScheduledMessage mirrors the backend ScheduledMessageResponse: id, cid, user, message (content without an ID; mentioned_users holds user IDs), scheduled_at, status, failure_reason, created_at, updated_at, and channel (query results only). Status values are exposed as STATUS_* constants.
  • Event gains scheduledMessage and messageId (the sent message's ID on scheduled_message.sent).
  • New doc page docs/messages/scheduled_messages.md.

Not added, on purpose:

  • include_scheduled_messages on GetOrCreateChannel: the backend marks it ignore_if_server_side, so it does nothing for a server SDK.
  • App settings (chat_scheduled_messages_enabled, max lead time): not exposed through the app settings API.
  • CHANGELOG.md: generated at release time.

How to verify

  1. ./gradlew test --tests '*ScheduledMessageTest*' passes (8 serialization tests, no API credentials needed).
  2. ./gradlew spotlessCheck javadoc passes.
  3. ScheduledMessageIntegrationTest (schedule, query, update, delete, send now against a real app) runs only with STREAM_SCHEDULED_MESSAGES_ENABLED=true, because the feature is behind a per-app flag that is off on the CI app. It has not been run yet: no app with the feature is available until the backend ships.

🤖 Generated with Claude Code

nijeesh-stream and others added 4 commits October 15, 2026 00:17
Message.send gains scheduledAt, and its response carries the stored
scheduled message. A new ScheduledMessage model lists (query), edits
(update), cancels (delete) and sends early (sendNow) the scheduled
messages of any user. Event reads scheduled_message and message_id for
the scheduled_message.* events.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The v1 API returns a scheduled message's custom fields as top-level keys
of its message object, as for regular messages, not under "custom".
Drop the custom field so they land in getAdditionalFields(), as on Message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant