Skip to content

feat(sendblue): add Sendblue iMessage/SMS integration with tools and triggers#4917

Merged
waleedlatif1 merged 7 commits into
stagingfrom
feat/sendblue-integration
Jun 9, 2026
Merged

feat(sendblue): add Sendblue iMessage/SMS integration with tools and triggers#4917
waleedlatif1 merged 7 commits into
stagingfrom
feat/sendblue-integration

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Add Sendblue integration (iMessage/SMS) — API-key auth via sb-api-key-id / sb-api-secret-key, base https://api.sendblue.com
  • 5 tools: send_message, send_group_message, evaluate_service (iMessage vs SMS lookup), send_typing_indicator, get_message
  • 2 webhook triggers: message_received (inbound) and message_status_updated (outbound status), with a provider handler that routes by is_outbound, dedupes on message_handle, and maps the full payload
  • Block with operation dropdown + conditional fields, SendblueBlockMeta (8 templates, 3 skills), brand icon, and generated docs (incl. a manual description section)

Type of Change

  • New feature

Testing

Tested manually against the live Sendblue API:

  • evaluate-service, send-typing-indicator, get_message, /api/lines, /accounts/limits return exactly the shapes the tools map
  • Inbound webhook payload verified field-for-field against Sendblue's documented example; trigger outputs ↔ handler formatInput keys diff to zero
  • tsc clean, biome clean, check:api-validation passes

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jun 9, 2026 2:39am

Request Review

@cursor

cursor Bot commented Jun 9, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
New third-party messaging and inbound webhooks handle PII (phone numbers, message content) and API secrets; webhook routing/dedup logic must stay correct to avoid missed or duplicate runs.

Overview
Adds a full Sendblue integration for iMessage and SMS: API-key auth (sb-api-key-id / sb-api-secret-key), five HTTP tools against api.sendblue.com, a workflow block with operation-specific fields and triggers, and catalog/docs wiring.

Tools & block: New tools cover single/group send (text, media, iMessage styles), iMessage-vs-SMS evaluation, typing indicators, and message lookup. The sendblue block registers in block/tool registries with templates, skills, and conditional UI (including newline-split group numbers).

Webhooks: Two triggers—Message Received (inbound) and Message Status Updated (outbound)—with a provider handler that routes on is_outbound, dedupes with message_handle plus status for status callbacks, and normalizes payloads for workflows.

Docs & codegen: SendblueIcon, integrations JSON, tools/triggers MDX, and icon maps; generate-docs.ts now prefers authMode for auth type and advances param parsing past nested blocks.

Reviewed by Cursor Bugbot for commit cb8de5b. Configure here.

Comment thread apps/sim/lib/webhooks/providers/sendblue.ts
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

1 issue from previous review remains unresolved.

Fix All in Cursor

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit e945547. Configure here.

@greptile-apps

greptile-apps Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds a complete Sendblue iMessage/SMS integration: 5 tools (send_message, send_group_message, evaluate_service, send_typing_indicator, get_message), 2 webhook triggers (message_received, message_status_updated), a block with an operation dropdown, registry entries, icon assets, and generated docs. The PR also backfills two generator fixes — extractAuthType now prefers the authoritative authMode declaration, and extractToolInfo skips nested array items descriptors when building the docs table.

  • Webhook routing is correct: matchEvent filters by is_outbound via SENDBLUE_TRIGGER_IS_OUTBOUND; extractIdempotencyId keys outbound events as {handle}:{status} so each SENT → DELIVERED transition fires independently while true retries are deduped.
  • Credential params use visibility: 'user-only' throughout, and header construction calls .trim() on both keys before sending.
  • The integrations.json entry now carries authType: \"api-key\", consistent with the block's AuthMode.ApiKey, after the generator fix.

Confidence Score: 5/5

Safe to merge — all new code is additive, credential handling is correct, and the webhook routing logic has been validated against Sendblue's documented payload schema.

The integration introduces only new files and registry additions; no existing code paths are modified outside the docs generator (two narrow, well-tested fixes). Credential visibility, auth header construction, idempotency keying, and authType in the catalog are all correct. The single comment is a UX suggestion that does not affect correctness or data integrity.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/lib/webhooks/providers/sendblue.ts Webhook provider handler routes by is_outbound flag via SENDBLUE_TRIGGER_IS_OUTBOUND; correctly deduplicates on {handle}:{status} for outbound, handle alone for inbound. Falls through to true for unknown triggerId (previously flagged P2).
apps/sim/blocks/blocks/sendblue.ts Block config with 5-operation dropdown, conditional subblocks for each operation, correct AuthMode.ApiKey, trigger integration, and 8 template entries.
apps/sim/triggers/sendblue/utils.ts Shared trigger utilities: SENDBLUE_TRIGGER_IS_OUTBOUND routing map, setup instructions builder, and shared buildSendblueOutputs() — all snake_case after previous normalisation.
apps/sim/tools/sendblue/send_message.ts New tool: single-recipient iMessage/SMS send via Sendblue; credential params use correct user-only visibility, filterUndefined on body, framework handles non-2xx before transformResponse.
apps/sim/tools/sendblue/send_group_message.ts New group-message tool; both content and media_url are optional, but at least one must be provided per the Sendblue API — no client-side guard expresses this constraint.
apps/sim/tools/sendblue/utils.ts Credential headers builder with .trim(), shared base param fields with user-only visibility — complies with credential visibility rule.
scripts/generate-docs.ts Two fixes: extractAuthType now reads authoritative authMode before falling back to heuristics; extractToolInfo advances lastIndex past array items blocks to prevent spurious doc rows.
apps/sim/lib/integrations/integrations.json Sendblue entry with authType: "api-key" — correctly matches block's AuthMode.ApiKey after generator fix.

Sequence Diagram

sequenceDiagram
    participant User as Sim Workflow
    participant Block as SendblueBlock
    participant Tool as Tool Executor
    participant SB as Sendblue API
    participant WH as Webhook Handler

    User->>Block: Select operation + credentials
    Block->>Tool: "executeTool(sendblue_*)"
    Tool->>SB: HTTP request (sb-api-key-id / sb-api-secret-key headers)
    SB-->>Tool: 200 OK / 4xx error
    Tool-->>Block: transformResponse output / throw on !ok

    Note over WH: Inbound & outbound events share one URL
    SB->>WH: POST webhook payload (is_outbound flag)
    WH->>WH: matchEvent: check SENDBLUE_TRIGGER_IS_OUTBOUND[triggerId]
    WH->>WH: extractIdempotencyId: handle + status key
    WH-->>User: formatInput → trigger outputs (snake_case)
Loading

Reviews (3): Last reviewed commit: "chore(sendblue): use SendblueSendStyle t..." | Re-trigger Greptile

Comment thread apps/sim/triggers/sendblue/utils.ts Outdated
Comment thread apps/sim/triggers/sendblue/utils.ts
Comment thread apps/sim/lib/integrations/integrations.json
@greptile-apps

greptile-apps Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces a complete Sendblue iMessage/SMS integration: 5 API tools (send_message, send_group_message, evaluate_service, send_typing_indicator, get_message), 2 webhook triggers (message_received, message_status_updated), a block with conditional UI fields, icon, catalog entry, and generated docs.

  • Tools & block: Follow established patterns — user-only visibility for credentials, filterUndefined body builders, transformResponse output mapping, and conditional subBlock fields for operation-specific inputs.
  • Triggers: Use the buildTriggerSubBlocks primary/secondary pattern correctly; the webhook provider routes inbound vs. outbound events via is_outbound, with message_handle as the idempotency key.
  • Minor issues: The integrations.json entry sets "authType": "none" while the block uses AuthMode.ApiKey; the matchEvent fallback returns true for unrecognized trigger IDs rather than false; and the auto-generated docs include a spurious items row in the send_group_message parameter table.

Confidence Score: 4/5

The integration is safe to merge; all tools follow established codebase conventions and credentials are handled correctly with user-only visibility.

The core tools, triggers, and block all follow the project's established patterns cleanly. The three findings are cosmetic or defensive: a catalog authType mismatch, a matchEvent fallback that could cause unexpected dispatch on malformed webhook configs, and a spurious items row in generated docs. None affect the happy path.

apps/sim/lib/webhooks/providers/sendblue.ts (matchEvent fallback) and apps/sim/lib/integrations/integrations.json (authType field) are worth a second look before merge.

Important Files Changed

Filename Overview
apps/sim/lib/webhooks/providers/sendblue.ts New webhook provider handler; routes inbound vs. outbound events via is_outbound; fallback return true for unknown trigger IDs could cause both event types to fire if config is malformed
apps/sim/blocks/blocks/sendblue.ts New block definition with 5 operations, conditional fields, and dual trigger wiring; follows established patterns cleanly
apps/sim/tools/sendblue/utils.ts Shared auth header builder and credential param fields; correctly uses user-only visibility for API keys per convention
apps/sim/triggers/sendblue/utils.ts Trigger output builder and setup instructions shared by both sendblue triggers; clean implementation
apps/sim/lib/integrations/integrations.json New catalog entry for Sendblue; authType is set to "none" but the block uses API key auth — should be "api-key"
apps/docs/content/docs/en/tools/sendblue.mdx Auto-generated docs; contains a spurious items row in the send_group_message input table that is not a real API parameter

Sequence Diagram

sequenceDiagram
    participant User as User / LLM
    participant Block as SendblueBlock
    participant Tool as sendblue_* Tool
    participant API as Sendblue API
    participant WH as Webhook Handler
    participant Trigger as Sendblue Trigger

    User->>Block: Configure operation + credentials
    Block->>Tool: Dispatch selected tool
    Tool->>API: "POST/GET with sb-api-key-id & sb-api-secret-key headers"
    API-->>Tool: JSON response
    Tool-->>Block: success + output

    Note over WH,Trigger: Inbound / outbound path
    API->>WH: POST webhook payload (is_outbound: false/true)
    WH->>WH: getProviderConfig → triggerId
    WH->>WH: matchEvent: check is_outbound vs TRIGGER_IS_OUTBOUND map
    alt "is_outbound == false"
        WH->>Trigger: message_received trigger fires
    else "is_outbound == true"
        WH->>Trigger: message_status_updated trigger fires
    end
    WH->>WH: extractIdempotencyId → message_handle (dedup)
    WH->>WH: formatInput → structured output payload
Loading

Comments Outside Diff (2)

  1. apps/sim/lib/integrations/integrations.json, line 889 (link)

    P2 authType mismatch with block authMode

    The block declares authMode: AuthMode.ApiKey (two mandatory credential fields), yet the catalog entry uses "authType": "none". The integration catalog uses this field to filter/display auth requirements, so users browsing the catalog will see Sendblue listed as requiring no authentication. Compare with sendgrid, which correctly uses "authType": "api-key". This should be "api-key" to remain consistent with the block definition.

  2. apps/sim/lib/webhooks/providers/sendblue.ts, line 948 (link)

    P2 matchEvent passes all events for unrecognized trigger IDs

    When triggerId is undefined or not in TRIGGER_IS_OUTBOUND, the handler returns true, letting every Sendblue event (inbound and outbound) match the subscription. Since Sendblue sends both event types to the same webhook URL, a subscription whose triggerId is missing (e.g., due to a corrupted config) will fire regardless of the payload's is_outbound flag, potentially triggering the wrong workflow on every event. Returning false for the unrecognized-trigger branch is safer.

Reviews (2): Last reviewed commit: "feat(sendblue): add Sendblue iMessage/SM..." | Re-trigger Greptile

Comment thread apps/docs/content/docs/en/tools/sendblue.mdx
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit cb8de5b. Configure here.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

Update: all of Greptile's flagged items are addressed in commits a645f3e..842fdfe (its summary above was generated on the original commit and is now stale):

  • authType → fixed to api-key; root-caused in the docs generator (extractAuthType now reads the authoritative authMode). ✅ resolved
  • spurious items row → fixed at the source (generator no longer parses an array param's nested items: descriptor as a param). ✅ resolved
  • matchEvent fallback returns true for unknown/missing triggerId → intentional. This matches the established convention (emailbison uses if (!triggerId) return true) and is fail-open: returning false would drop events (data loss) if the trigger map ever drifted from the registry. Both Sendblue triggers are always in the map, so the fallback is unreachable for known triggers; when a triggerId is present and known, is_outbound filtering applies normally.

Cursor Bugbot is clean on the latest commit, and both /validate-integration and /validate-trigger pass.

Avoids a webhook-providers -> triggers cross-subgraph import (single source
of truth in the handler, its only runtime consumer).
@waleedlatif1 waleedlatif1 merged commit a72e35e into staging Jun 9, 2026
9 checks passed
@waleedlatif1 waleedlatif1 deleted the feat/sendblue-integration branch June 9, 2026 02:41
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