Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/correct-blocked-reason.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@senderkit/sdk": patch
---

Correct the `blocked` message documentation. The detailed abuse-scan trigger is operator-only and is never returned on the public message read surface (`messages.list` / `messages.get`), so the previously-documented `Message.blockedReason` field (which the API never populated) has been removed. A blocked message is identified by its `blocked` status and a generic entry on its `timeline`. The `blocked` status itself is unchanged.
3 changes: 2 additions & 1 deletion packages/sdk/src/mcp-schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ const emailEnvelope = {
* The ten message lifecycle statuses (mirrors the app's `messageStatusEnum`).
* Bounces normalize to `failed` with the reason on the message timeline.
* `blocked` is a terminal state set when the outbound abuse scanner halts a
* send (the human-readable trigger is on the message's `blockedReason`).
* send. The detailed trigger is operator-only and is never returned on the
* message; a blocked message carries only a generic reason on its timeline.
*/
export const MESSAGE_STATUSES = [
"scheduled",
Expand Down
6 changes: 3 additions & 3 deletions packages/sdk/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,15 +195,15 @@ export interface Message {
publicId: string;
/**
* Lifecycle status (one of `MESSAGE_STATUSES`). A `blocked` message was
* halted by the outbound abuse scanner; `blockedReason` carries the trigger.
* halted by the outbound abuse scanner. The detailed trigger is operator-only
* and is not returned here — a blocked message exposes only its `blocked`
* status and a generic entry on its `timeline`.
*/
status: string;
channel: Channel;
templateSlug: string | null;
recipient: string;
createdAt: string;
/** Human-readable reason a `blocked` message was halted. Absent otherwise. */
blockedReason?: string | null;
[key: string]: unknown;
}

Expand Down