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
20 changes: 20 additions & 0 deletions .changeset/fix-blocked-reason-not-returned.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
"@senderkit/sdk": patch
---

Correct the `blocked` message documentation to match the API.

The previous release advertised a `Message.blockedReason` field carrying the
"human-readable trigger" for a blocked send. senderkit-app never returned it:
the REST `messages.list` / `messages.get` projection (and the MCP tools built
on it) deliberately omit the abuse detection breakdown, which is operator-only.
The app has now codified this (the customer-facing `timeline` carries only a
generic "Blocked by automated content safety checks." entry; the detailed
reason stays in the operator-only admin abuse review).

- Remove the never-populated `Message.blockedReason` field. Reads still expose
any extra server fields through the existing index signature, so this only
drops a misleading type/doc — no field that the API actually sent.
- Update the `Message.status` and `MESSAGE_STATUSES` docs to stop pointing at
`blockedReason` and describe the generic, customer-facing block reason
instead.
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 detection breakdown is operator-only and never returned by
* the API; a blocked message's `timeline` carries only a generic block entry.
*/
export const MESSAGE_STATUSES = [
"scheduled",
Expand Down
7 changes: 4 additions & 3 deletions packages/sdk/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,15 +195,16 @@ 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 detection breakdown is
* operator-only and is never returned by the API; the customer-facing
* `timeline` carries only a generic block entry ("Blocked by automated
* content safety checks.").
*/
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