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
10 changes: 10 additions & 0 deletions .changeset/quiet-message-block-reason.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@senderkit/sdk": patch
---

Stop advertising `Message.blockedReason` on the message read type and in the
MCP status description. The customer-facing API (`messages.list` / `messages.get`,
plus the live tail) never returns the detailed abuse-scan trigger — it is
operator-only — so the optional field was always absent on the wire. A `blocked`
message still surfaces a generic "blocked" entry on its `timeline`. The `Message`
type keeps its `[key: string]: unknown` index signature, so this is non-breaking.
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; a generic "blocked" entry is recorded on the message timeline. The
* detailed detection trigger is operator-only and not returned by the API.
*/
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; a generic "blocked" entry appears on
* the message `timeline`. The detailed detection breakdown is operator-only
* and is never returned by the customer-facing API.
*/
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