Skip to content

[CHA-5933] feat: add scheduled messages support - #219

Open
nijeesh-stream wants to merge 3 commits into
masterfrom
feature/cha-5933-scheduled-messages
Open

nijeesh-stream wants to merge 3 commits into
masterfrom
feature/cha-5933-scheduled-messages

Conversation

@nijeesh-stream

@nijeesh-stream nijeesh-stream commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

TLDR

Adds server-side support for Chat scheduled messages: schedule a message for a user, then edit it, cancel it, send it right away, or list a user's scheduled messages. Backend endpoints are behind a per-app flag and not yet released; merge after backend CHA-5924 ships. Risk is low: the change adds new methods and nullable fields. One send-path tweak applies only when ScheduledAt is set (details below).

Linear: https://linear.app/stream/issue/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)
  • Commit message fits conventional commits. Important for CHANGELOG generation.

Description of the pull request

New IMessageClient methods, next to the reminder methods:

Method API
ScheduleMessageAsync(type, id, msg, userId, scheduledAt, options), or SendMessageAsync with SendMessageOptions.ScheduledAt POST /channels/{type}/{id}/message with scheduled_at; the response's new GenericMessageResponse.ScheduledMessage is set
UpdateScheduledMessageAsync(id, UpdateScheduledMessageRequest) PATCH /scheduled_messages/{id}
DeleteScheduledMessageAsync(id) DELETE /scheduled_messages/{id}
SendScheduledMessageNowAsync(id) POST /scheduled_messages/{id}/send_now
QueryScheduledMessagesAsync(QueryScheduledMessagesRequest) POST /scheduled_messages/query (UserId, Filter.Cid, Filter.Status, Sort, Limit, Next)

Models (src/Models/ScheduledMessage.cs): ScheduledMessage, ScheduledMessageContent (custom fields via GetData), ScheduledMessageLocation, ScheduledMessageChannel, the request and response types, and the ScheduledMessageStatus / ScheduledMessageFailureReason string constants. EventResponse gains ScheduledMessage and MessageId, so WebhookHelpers.ParseEvent exposes the scheduled_message.sent / .failed webhooks.

Send-path note: SendMessageAsync always sends is_pending_message (false by default), and scheduled sends do the same, exactly like a live send. An explicit false overrides the channel type's mark_messages_pending setting, so a scheduled message into such a channel is sent normally instead of failing with pending_not_supported. Requires a backend with GetStream/chat#18727, which accepts is_pending_message: false with scheduled_at (older backends answered 400 scheduled_at cannot be combined with pending). Merge and release only after that is deployed everywhere. IsPendingMessage = true with ScheduledAt is still rejected by the API.

Docs: new docs/messages/scheduled_messages.md, plus the webhook events in docs/webhooks/webhook_events.md. CHANGELOG is left to the release tooling.

Not added: include_scheduled_messages on GetOrCreateChannel (the backend ignores it for server-side calls), app settings (the chat_scheduled_messages_* flags aren't exposed through the app settings API), and a permission constant (Resource only lists legacy v1 permissions).

Tests

  • tests/ScheduledMessageRequestTests.cs: checks request and response shapes, and webhook parsing, against a stubbed HttpMessageHandler. It needs no credentials and always runs.
  • MessageClientTests: live round trip (schedule, query, update, send now, delete). It calls Assert.Ignore when the app has the feature off or the backend ignores scheduled_at, so CI stays green until the flag is on for the CI app.
  • Local results: the live tests pass (5/5) against a local backend built from the backend branch feature/cha-5924-scheduled-messages-channel-state, using an app with the flag on. They show as ignored against an app with the flag off. The net6.0 build has no new warnings.

🤖 Generated with Claude Code

nijeesh-stream and others added 3 commits October 15, 2026 00:29
Add SendMessageOptions.ScheduledAt and ScheduleMessageAsync (SendMessage
with scheduled_at), plus UpdateScheduledMessageAsync,
DeleteScheduledMessageAsync, SendScheduledMessageNowAsync and
QueryScheduledMessagesAsync, the ScheduledMessage models, and the
scheduled_message fields on GenericMessageResponse and EventResponse.

A scheduled send leaves out is_pending_message when it is false: the API
rejects scheduled_at combined with any pending field.

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Leaving out is_pending_message: false made scheduled sends into channel
types that mark messages pending fail with pending_not_supported, while
the same live send succeeds. The API accepts false with scheduled_at
since GetStream/chat#18727.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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