Skip to content

Commit a72e35e

Browse files
authored
feat(sendblue): add Sendblue iMessage/SMS integration with tools and triggers (#4917)
* feat(sendblue): add Sendblue iMessage/SMS integration with tools and triggers * fix(sendblue): address review — status-aware webhook dedup, shared routing map, uniform output casing, api-key authType * fix(docs-gen): skip nested array `items` descriptor in tool input tables * chore(sendblue): use SendblueSendStyle type, trim URL identifiers * fix(sendblue): keep is_outbound routing map local to the webhook handler Avoids a webhook-providers -> triggers cross-subgraph import (single source of truth in the handler, its only runtime consumer). * fix(sendblue): remove invalid `tags` from block config (belongs on BlockMeta)
1 parent 4f00baf commit a72e35e

28 files changed

Lines changed: 1757 additions & 0 deletions

apps/docs/components/icons.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2047,6 +2047,21 @@ export function TwilioIcon(props: SVGProps<SVGSVGElement>) {
20472047
)
20482048
}
20492049

2050+
export function SendblueIcon(props: SVGProps<SVGSVGElement>) {
2051+
return (
2052+
<svg {...props} viewBox='0 0 72 72' fill='none' xmlns='http://www.w3.org/2000/svg'>
2053+
<path
2054+
fill='currentColor'
2055+
d='M58.5425 5.19973C53.9872 5.19973 50.2944 8.89316 50.2944 13.4492C50.2944 18.0053 53.9872 21.6987 58.5425 21.6987C63.0978 21.6987 66.7906 18.0053 66.7907 13.4492C66.7907 8.89316 63.0978 5.19973 58.5425 5.19973Z'
2056+
/>
2057+
<path
2058+
fill='currentColor'
2059+
d='M0.0122017 36C0.0122012 41.6798 4.37038 46.3269 9.92916 46.8072C6.33936 51.07 6.54347 57.4463 10.5535 61.457C14.5635 65.4676 20.9387 65.6718 25.2008 62.0814C25.669 67.6411 30.3274 72 36.0062 72C41.685 72 46.3314 67.6411 46.8116 62.0814C51.0737 65.6718 57.4489 65.4676 61.4589 61.457C65.4689 57.4463 65.673 51.0701 62.0832 46.8072C67.642 46.3389 72.0002 41.6798 72.0002 36C72.0002 30.008 67.1378 25.1448 61.1468 25.1448C60.7266 25.1448 60.3183 25.1808 59.9101 25.2288C59.4659 25.2769 59.0097 25.2889 58.5415 25.2889C56.9927 25.2889 55.5159 24.9887 54.1713 24.4483C51.1458 23.2475 48.7446 20.8339 47.544 17.8199C47.0037 16.463 46.7035 14.986 46.7035 13.449C46.7035 12.9807 46.7155 12.5364 46.7636 12.0801C46.8116 11.6718 46.8476 11.2635 46.8476 10.8553C46.8476 4.86326 41.9852 1.65468e-05 35.9942 1.60229e-05C30.3154 1.55264e-05 25.669 4.35892 25.1888 9.91862C20.9267 6.32823 14.5515 6.53237 10.5415 10.543C6.53146 14.5537 6.32736 20.93 9.91715 25.1928C4.35837 25.6611 0.000195295 30.3202 0.000194799 36L0.0122017 36Z'
2060+
/>
2061+
</svg>
2062+
)
2063+
}
2064+
20502065
export function ImageIcon(props: SVGProps<SVGSVGElement>) {
20512066
return (
20522067
<svg

apps/docs/components/ui/icon-mapping.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ import {
167167
SapS4HanaIcon,
168168
SESIcon,
169169
SecretsManagerIcon,
170+
SendblueIcon,
170171
SendgridIcon,
171172
SentryIcon,
172173
SerperIcon,
@@ -392,6 +393,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
392393
sap_concur: SapConcurIcon,
393394
sap_s4hana: SapS4HanaIcon,
394395
secrets_manager: SecretsManagerIcon,
396+
sendblue: SendblueIcon,
395397
sendgrid: SendgridIcon,
396398
sentry: SentryIcon,
397399
serper: SerperIcon,

apps/docs/content/docs/en/tools/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@
157157
"sap_concur",
158158
"sap_s4hana",
159159
"secrets_manager",
160+
"sendblue",
160161
"sendgrid",
161162
"sentry",
162163
"serper",
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
---
2+
title: Sendblue
3+
description: Send and receive iMessage and SMS
4+
---
5+
6+
import { BlockInfoCard } from "@/components/ui/block-info-card"
7+
8+
<BlockInfoCard
9+
type="sendblue"
10+
color="#008BFF"
11+
/>
12+
13+
{/* MANUAL-CONTENT-START:intro */}
14+
## Manual Description
15+
16+
Sendblue connects your agents to iMessage and SMS through your own dedicated phone number. Use it to text one person or a group, attach images and other media, check whether a number can receive iMessage before you send, show a typing indicator, and look up the delivery status of any message.
17+
18+
Authentication uses a Sendblue **API Key ID** and **API Secret Key**, sent as the `sb-api-key-id` and `sb-api-secret-key` headers. You can find both in your [Sendblue dashboard](https://dashboard.sendblue.com). Every message is sent from one of your registered Sendblue lines, supplied as the **From Number** in E.164 format (for example `+15551234567`).
19+
20+
**Operations**
21+
22+
- **Send Message** — send an iMessage or SMS to a single recipient. Provide message text, a media URL, or both, and optionally apply an iMessage expressive style (celebration, fireworks, lasers, confetti, and more).
23+
- **Send Group Message** — send to multiple recipients at once. Pass one recipient per line; reuse the returned `group_id` to keep replying in the same thread.
24+
- **Evaluate Service** — check whether a number is reachable on iMessage or only SMS, so you can branch before sending.
25+
- **Send Typing Indicator** — show a recipient that a reply is being composed (one-to-one chats only).
26+
- **Get Message** — retrieve a single message and its current status by message handle.
27+
28+
**Triggers**
29+
30+
- **Message Received** — fires on every inbound message. Configure it as the **Receive** webhook in your Sendblue dashboard.
31+
- **Message Status Updated** — fires when an outbound message changes state (`SENT`, `DELIVERED`, `ERROR`). Configure it as the **Outbound** webhook, or pass its URL per message as `status_callback`.
32+
33+
Each trigger generates its own webhook URL — paste the matching URL into the corresponding field in your Sendblue dashboard.
34+
{/* MANUAL-CONTENT-END */}
35+
36+
37+
## Usage Instructions
38+
39+
Send iMessages and SMS to individuals or groups, check whether a number supports iMessage, show typing indicators, and look up message status with Sendblue. Trigger workflows on inbound messages and delivery status updates.
40+
41+
42+
43+
## Tools
44+
45+
### `sendblue_send_message`
46+
47+
Send an iMessage or SMS to a single recipient via Sendblue.
48+
49+
#### Input
50+
51+
| Parameter | Type | Required | Description |
52+
| --------- | ---- | -------- | ----------- |
53+
| `number` | string | Yes | Recipient phone number in E.164 format \(e.g., +19998887777\) |
54+
| `from_number` | string | Yes | One of your registered Sendblue phone numbers to send from, in E.164 format \(e.g., +18887776666\) |
55+
| `content` | string | No | Message text content. Either content or media_url must be provided. |
56+
| `media_url` | string | No | URL of a media file to send. Either content or media_url must be provided. |
57+
| `send_style` | string | No | iMessage expressive style \(e.g., celebration, fireworks, lasers, confetti, balloons, invisible, slam\). |
58+
| `status_callback` | string | No | Webhook URL that Sendblue will POST message status updates to. |
59+
60+
#### Output
61+
62+
| Parameter | Type | Description |
63+
| --------- | ---- | ----------- |
64+
| `status` | string | Message status: QUEUED, SENT, DELIVERED, or ERROR |
65+
| `message_handle` | string | Unique identifier for tracking the message |
66+
| `account_email` | string | Email of the account that sent the message |
67+
| `content` | string | Message content |
68+
| `is_outbound` | boolean | Whether this is an outbound message |
69+
| `from_number` | string | Sending phone number |
70+
| `number` | string | Recipient phone number |
71+
| `media_url` | string | URL of attached media |
72+
| `send_style` | string | iMessage expressive style applied |
73+
| `seat_id` | string | UUID of the seat that sent the message |
74+
| `sender_email` | string | Email of the seat \(user\) that sent the message |
75+
| `error_code` | number | Numeric error code if the message failed |
76+
| `error_message` | string | Error message if the message failed |
77+
| `date_created` | string | When the message was created |
78+
| `date_updated` | string | When the message was last updated |
79+
80+
### `sendblue_send_group_message`
81+
82+
Send an iMessage or SMS to a group of recipients via Sendblue.
83+
84+
#### Input
85+
86+
| Parameter | Type | Required | Description |
87+
| --------- | ---- | -------- | ----------- |
88+
| `numbers` | array | Yes | Recipient phone numbers in E.164 format \(e.g., \["+19998887777", "+13334445555"\]\) |
89+
| `from_number` | string | Yes | One of your registered Sendblue phone numbers to send from, in E.164 format \(e.g., +18887776666\) |
90+
| `content` | string | No | Message text content. Either content or media_url must be provided. |
91+
| `media_url` | string | No | URL of a media file to send. Either content or media_url must be provided. |
92+
| `send_style` | string | No | iMessage expressive style \(e.g., celebration, fireworks, lasers, confetti, balloons, invisible, slam\). |
93+
| `group_id` | string | No | Unique identifier of an existing group to send to. Omit to start a new group. |
94+
| `status_callback` | string | No | Webhook URL that Sendblue will POST message status updates to. |
95+
96+
#### Output
97+
98+
| Parameter | Type | Description |
99+
| --------- | ---- | ----------- |
100+
| `status` | string | Message status: QUEUED, SENT, DELIVERED, or ERROR |
101+
| `message_handle` | string | Unique identifier for tracking the message |
102+
| `group_id` | string | Identifier of the group the message was sent to |
103+
| `participants` | array | Phone numbers participating in the group |
104+
| `account_email` | string | Email of the account that sent the message |
105+
| `content` | string | Message content |
106+
| `is_outbound` | boolean | Whether this is an outbound message |
107+
| `from_number` | string | Sending phone number |
108+
| `number` | string | Recipient phone number |
109+
| `media_url` | string | URL of attached media |
110+
| `send_style` | string | iMessage expressive style applied |
111+
| `seat_id` | string | UUID of the seat that sent the message |
112+
| `sender_email` | string | Email of the seat \(user\) that sent the message |
113+
| `error_code` | number | Numeric error code if the message failed |
114+
| `error_message` | string | Error message if the message failed |
115+
| `date_created` | string | When the message was created |
116+
| `date_updated` | string | When the message was last updated |
117+
118+
### `sendblue_evaluate_service`
119+
120+
Check whether a phone number can receive iMessage or only SMS.
121+
122+
#### Input
123+
124+
| Parameter | Type | Required | Description |
125+
| --------- | ---- | -------- | ----------- |
126+
| `number` | string | Yes | Phone number to evaluate, in E.164 format \(e.g., +19998887777\) |
127+
128+
#### Output
129+
130+
| Parameter | Type | Description |
131+
| --------- | ---- | ----------- |
132+
| `number` | string | The evaluated phone number in E.164 format |
133+
| `service` | string | The service the number supports: iMessage or SMS |
134+
135+
### `sendblue_send_typing_indicator`
136+
137+
Display a typing indicator to a recipient (not supported in group chats).
138+
139+
#### Input
140+
141+
| Parameter | Type | Required | Description |
142+
| --------- | ---- | -------- | ----------- |
143+
| `number` | string | Yes | Recipient's phone number in E.164 format \(e.g., +19998887777\) |
144+
| `from_number` | string | No | Your Sendblue line number to send from, in E.164 format. |
145+
146+
#### Output
147+
148+
| Parameter | Type | Description |
149+
| --------- | ---- | ----------- |
150+
| `status` | string | Delivery status of the typing indicator \(e.g., QUEUED\) |
151+
| `status_code` | number | Numeric status code returned by Sendblue |
152+
| `number` | string | The recipient phone number |
153+
| `error_message` | string | Error details, null on success |
154+
155+
### `sendblue_get_message`
156+
157+
Retrieve a single message and its current status by message handle/ID.
158+
159+
#### Input
160+
161+
| Parameter | Type | Required | Description |
162+
| --------- | ---- | -------- | ----------- |
163+
| `message_id` | string | Yes | The message handle/ID returned when the message was sent. |
164+
165+
#### Output
166+
167+
| Parameter | Type | Description |
168+
| --------- | ---- | ----------- |
169+
| `status` | string | Current message status |
170+
| `message_handle` | string | Unique message identifier |
171+
| `account_email` | string | Email of the account |
172+
| `content` | string | Message content |
173+
| `is_outbound` | boolean | Whether the message is outbound |
174+
| `from_number` | string | Sending phone number |
175+
| `number` | string | Recipient phone number |
176+
| `to_number` | string | Destination phone number |
177+
| `media_url` | string | URL of attached media |
178+
| `message_type` | string | Message category: message or group |
179+
| `service` | string | Messaging service: iMessage, SMS, or RCS |
180+
| `group_id` | string | Group identifier \(empty for non-group\) |
181+
| `group_display_name` | string | Group chat name |
182+
| `participants` | array | Participant phone numbers |
183+
| `send_style` | string | Expressive style applied |
184+
| `was_downgraded` | boolean | True if the recipient lacks iMessage support |
185+
| `opted_out` | boolean | True if the recipient has opted out |
186+
| `plan` | string | Account plan type |
187+
| `sendblue_number` | string | Sendblue phone number used |
188+
| `seat_id` | string | Seat UUID |
189+
| `sender_email` | string | Email of the sending seat |
190+
| `error_code` | number | Numeric error code if failed |
191+
| `error_message` | string | Error message if failed |
192+
| `error_reason` | string | Additional error context |
193+
| `error_detail` | string | Detailed error information |
194+
| `date_sent` | string | ISO 8601 creation timestamp |
195+
| `date_updated` | string | ISO 8601 last-update timestamp |
196+
197+

apps/docs/content/docs/en/triggers/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"outlook",
3939
"resend",
4040
"salesforce",
41+
"sendblue",
4142
"servicenow",
4243
"slack",
4344
"stripe",
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
---
2+
title: Sendblue
3+
description: Available Sendblue triggers for automating workflows
4+
---
5+
6+
import { BlockInfoCard } from "@/components/ui/block-info-card"
7+
8+
<BlockInfoCard
9+
type="sendblue"
10+
color="#008BFF"
11+
/>
12+
13+
Sendblue provides 2 triggers for automating workflows based on events.
14+
15+
## Triggers
16+
17+
### Sendblue Message Received
18+
19+
Trigger when an inbound iMessage or SMS is received in Sendblue
20+
21+
#### Output
22+
23+
| Parameter | Type | Description |
24+
| --------- | ---- | ----------- |
25+
| `account_email` | string | Email of the Sendblue account |
26+
| `content` | string | Message text content |
27+
| `media_url` | string | CDN link to attached media, if any |
28+
| `is_outbound` | boolean | True for outbound messages, false for inbound |
29+
| `status` | string | Message status \(e.g., RECEIVED, QUEUED, SENT, DELIVERED, ERROR\) |
30+
| `error_code` | number | Error identifier, null if none |
31+
| `error_message` | string | Descriptive error text, null if none |
32+
| `error_reason` | string | Additional error context, null if none |
33+
| `error_detail` | string | Detailed error information, null if none |
34+
| `message_handle` | string | Sendblue message identifier \(use to deduplicate\) |
35+
| `date_sent` | string | ISO 8601 creation timestamp |
36+
| `date_updated` | string | ISO 8601 last-update timestamp |
37+
| `from_number` | string | E.164 sender phone number |
38+
| `number` | string | E.164 recipient/counterparty phone number |
39+
| `to_number` | string | E.164 destination phone number |
40+
| `was_downgraded` | boolean | True if the recipient lacks iMessage support |
41+
| `plan` | string | Account plan type |
42+
| `message_type` | string | Message category \(e.g., message, group\) |
43+
| `group_id` | string | Group identifier, empty for non-group messages |
44+
| `participants` | array | Participant phone numbers for group messages |
45+
| `send_style` | string | Expressive style if applied |
46+
| `opted_out` | boolean | True if the recipient has opted out |
47+
| `sendblue_number` | string | Sendblue phone number used |
48+
| `service` | string | Messaging service \(iMessage or SMS\) |
49+
| `group_display_name` | string | Group chat name, null for non-group messages |
50+
| `sender_email` | string | Email of the user who sent the message |
51+
| `seat_id` | string | Seat UUID, null if absent |
52+
| `raw` | string | Complete raw webhook payload from Sendblue as a JSON string |
53+
54+
55+
---
56+
57+
### Sendblue Message Status Updated
58+
59+
Trigger when an outbound message status changes (SENT, DELIVERED, ERROR) in Sendblue
60+
61+
#### Output
62+
63+
| Parameter | Type | Description |
64+
| --------- | ---- | ----------- |
65+
| `account_email` | string | Email of the Sendblue account |
66+
| `content` | string | Message text content |
67+
| `media_url` | string | CDN link to attached media, if any |
68+
| `is_outbound` | boolean | True for outbound messages, false for inbound |
69+
| `status` | string | Message status \(e.g., RECEIVED, QUEUED, SENT, DELIVERED, ERROR\) |
70+
| `error_code` | number | Error identifier, null if none |
71+
| `error_message` | string | Descriptive error text, null if none |
72+
| `error_reason` | string | Additional error context, null if none |
73+
| `error_detail` | string | Detailed error information, null if none |
74+
| `message_handle` | string | Sendblue message identifier \(use to deduplicate\) |
75+
| `date_sent` | string | ISO 8601 creation timestamp |
76+
| `date_updated` | string | ISO 8601 last-update timestamp |
77+
| `from_number` | string | E.164 sender phone number |
78+
| `number` | string | E.164 recipient/counterparty phone number |
79+
| `to_number` | string | E.164 destination phone number |
80+
| `was_downgraded` | boolean | True if the recipient lacks iMessage support |
81+
| `plan` | string | Account plan type |
82+
| `message_type` | string | Message category \(e.g., message, group\) |
83+
| `group_id` | string | Group identifier, empty for non-group messages |
84+
| `participants` | array | Participant phone numbers for group messages |
85+
| `send_style` | string | Expressive style if applied |
86+
| `opted_out` | boolean | True if the recipient has opted out |
87+
| `sendblue_number` | string | Sendblue phone number used |
88+
| `service` | string | Messaging service \(iMessage or SMS\) |
89+
| `group_display_name` | string | Group chat name, null for non-group messages |
90+
| `sender_email` | string | Email of the user who sent the message |
91+
| `seat_id` | string | Seat UUID, null if absent |
92+
| `raw` | string | Complete raw webhook payload from Sendblue as a JSON string |
93+

0 commit comments

Comments
 (0)