<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: David Harvey</title>
    <description>The latest articles on DEV Community by David Harvey (@blooio).</description>
    <link>https://dev.to/blooio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3610727%2Fdf6f46b7-85ff-428f-af86-be56d688e11b.jpg</url>
      <title>DEV Community: David Harvey</title>
      <link>https://dev.to/blooio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/blooio"/>
    <language>en</language>
    <item>
      <title>How to Send iMessages Programmatically (REST API, Python &amp; Node.js)</title>
      <dc:creator>David Harvey</dc:creator>
      <pubDate>Sun, 28 Jun 2026 03:45:08 +0000</pubDate>
      <link>https://dev.to/blooio-messages/how-to-send-imessages-programmatically-rest-api-python-nodejs-3oo6</link>
      <guid>https://dev.to/blooio-messages/how-to-send-imessages-programmatically-rest-api-python-nodejs-3oo6</guid>
      <description>&lt;p&gt;If you've ever tried to &lt;strong&gt;send an iMessage programmatically&lt;/strong&gt;, you've probably hit the same wall everyone does: Apple has no public iMessage API. There's no &lt;code&gt;POST /imessage&lt;/code&gt; in the developer docs, no SDK, no OAuth scope. Yet "blue bubble" delivery has 3–4× the open rates of SMS, so the demand to &lt;strong&gt;send iMessages from code&lt;/strong&gt; — for CRMs, bots, notifications, and outbound — keeps growing.&lt;/p&gt;

&lt;p&gt;This guide covers the realistic options, then walks through actually sending and receiving iMessages over a &lt;strong&gt;REST API&lt;/strong&gt; with working &lt;strong&gt;Python&lt;/strong&gt;, &lt;strong&gt;Node.js&lt;/strong&gt;, and &lt;strong&gt;curl&lt;/strong&gt; examples you can paste and run today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why there's no official iMessage API
&lt;/h2&gt;

&lt;p&gt;iMessage is a closed, end-to-end-encrypted protocol tied to Apple IDs and Apple hardware. Apple has never shipped a public API to send iMessages, and "Messages for Business" is a support-inbox product gated behind an approval process — not a way to send outbound messages from a script.&lt;/p&gt;

&lt;p&gt;So historically, developers reached for hacks:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Works from a server?&lt;/th&gt;
&lt;th&gt;Reliability&lt;/th&gt;
&lt;th&gt;Receiving messages&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AppleScript / &lt;code&gt;osascript&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;No — needs a logged-in Mac with Messages open&lt;/td&gt;
&lt;td&gt;Brittle&lt;/td&gt;
&lt;td&gt;Polling the local SQLite &lt;code&gt;chat.db&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Mac-only, breaks on macOS updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shortcuts automation&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Brittle&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Manual, not built for scale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Just use SMS" (Twilio etc.)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Green bubbles, no typing indicators/tapbacks/HD media&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosted iMessage REST API&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Yes (webhooks)&lt;/td&gt;
&lt;td&gt;What this guide uses&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The AppleScript route is fine for a one-off script on your own Mac. The moment you want to send from a server, send at scale, or &lt;em&gt;receive&lt;/em&gt; replies reliably, you need a hosted API that manages the Apple side for you and exposes a normal HTTP interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;For the examples below I'm using &lt;a href="https://blooio.com/integrations/api" rel="noopener noreferrer"&gt;Blooio&lt;/a&gt;, an iMessage REST API. Any provider with a similar HTTP surface will follow the same patterns — the concepts (Bearer auth, a send endpoint, webhooks for inbound) are what matter.&lt;/p&gt;

&lt;p&gt;You'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An API key (Blooio gives you one in the &lt;a href="https://app.blooio.com/signup" rel="noopener noreferrer"&gt;dashboard&lt;/a&gt; — no credit card, no A2P/10DLC registration, no DUNS number)&lt;/li&gt;
&lt;li&gt;A phone number you can test against&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Base URL for all calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.blooio.com/v2/api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Send your first iMessage (curl)
&lt;/h2&gt;

&lt;p&gt;The whole thing is one authenticated &lt;code&gt;POST&lt;/code&gt;. The chat is identified by the recipient's phone number (URL-encoded, because of the &lt;code&gt;+&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://api.blooio.com/v2/api/chats/%2B15551234567/messages"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer sk_live_your_key_here"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"text": "Hello from the command line 👋"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"message_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"msg_a1b2c3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"queued"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it — no Mac, no AppleScript, no polling. If the recipient has iMessage, it lands as a blue bubble.&lt;/p&gt;

&lt;h2&gt;
  
  
  Send an iMessage from Python
&lt;/h2&gt;

&lt;p&gt;The minimal version uses &lt;code&gt;requests&lt;/code&gt;. Note the &lt;code&gt;quote(..., safe='')&lt;/code&gt; on the phone number — forgetting to URL-encode the &lt;code&gt;+&lt;/code&gt; is the #1 cause of silent &lt;code&gt;400&lt;/code&gt;s.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;urllib.parse&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;

&lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BLOOIO_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.blooio.com/v2/api&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_imessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;chat_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;safe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;BASE_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/chats/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;chat_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;send_imessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+15551234567&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello from Python!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Message &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BLOOIO_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk_live_your_key_here
python send.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Send an iMessage from Node.js
&lt;/h2&gt;

&lt;p&gt;Node 18+ has native &lt;code&gt;fetch&lt;/code&gt;, so the basic case needs zero dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BLOOIO_API_KEY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.blooio.com/v2/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendImessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;BASE_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/chats/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;chatId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/messages`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Blooio &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendImessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;+15551234567&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello from Node.js!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Message &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Blue bubble or green? Check capability first
&lt;/h2&gt;

&lt;p&gt;Not every number can receive iMessage. If you're building an iMessage-first flow with SMS fallback, check capability before sending:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_imessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;chat_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;safe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;BASE_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/contacts/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;chat_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/capabilities&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;capabilities&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;imessage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;has_imessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+15551234567&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;send_imessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+15551234567&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Blue bubbles only ✨&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# fall back to your SMS provider here
&lt;/span&gt;    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Receiving iMessages (webhooks)
&lt;/h2&gt;

&lt;p&gt;Sending is half the story — to build a bot or a two-way CRM thread you need inbound messages. Instead of polling, you register a webhook URL and the API &lt;code&gt;POST&lt;/code&gt;s events to you. Verify the HMAC signature so you only trust real events:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:crypto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/webhooks/blooio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-blooio-signature&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-blooio-event&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BLOOIO_WEBHOOK_SECRET&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timingSafeEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message.received&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="c1"&gt;// ...reply, route to your CRM, trigger an LLM, etc.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Listening on :3001&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For local development, tunnel the endpoint with ngrok and point the webhook at the tunnel URL. Now you have a full send + receive loop — enough to build an &lt;strong&gt;iMessage bot&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating without writing code
&lt;/h2&gt;

&lt;p&gt;If you'd rather wire iMessage into existing tools than write a service, the same API drops into no-code/low-code platforms. Blooio has native nodes/actions for &lt;a href="https://blooio.com/integrations/n8n" rel="noopener noreferrer"&gt;n8n&lt;/a&gt;, &lt;a href="https://blooio.com/integrations/high-level" rel="noopener noreferrer"&gt;GoHighLevel&lt;/a&gt;, HubSpot, and Zapier — so "new lead in CRM → send iMessage" is a couple of clicks rather than a deploy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotchas worth knowing up front
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;URL-encode the phone number.&lt;/strong&gt; &lt;code&gt;+15551234567&lt;/code&gt; must become &lt;code&gt;%2B15551234567&lt;/code&gt;. This bites everyone once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No A2P/10DLC registration, DUNS, or campaign approval&lt;/strong&gt; with a hosted iMessage API — that paperwork is an SMS/carrier thing. iMessage rides Apple's network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use idempotency keys for retries.&lt;/strong&gt; Pass an &lt;code&gt;Idempotency-Key&lt;/code&gt; header derived from your domain entity (e.g. &lt;code&gt;order-123-shipped&lt;/code&gt;) so a retry never double-sends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Throttle bulk sends.&lt;/strong&gt; Don't fire 1,000 parallel requests — cap concurrency (e.g. &lt;code&gt;p-limit&lt;/code&gt; in Node, a semaphore in Python) and back off on &lt;code&gt;429&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;iMessage ≠ guaranteed.&lt;/strong&gt; If a number isn't on iMessage, check capability and fall back to SMS rather than assuming a blue bubble.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;You don't need a Mac mini farm or fragile AppleScript to &lt;strong&gt;send iMessages programmatically&lt;/strong&gt; anymore. A hosted &lt;strong&gt;iMessage REST API&lt;/strong&gt; turns it into a normal HTTP call — &lt;code&gt;POST&lt;/code&gt; to send, webhooks to receive — that works the same from &lt;strong&gt;Python&lt;/strong&gt;, &lt;strong&gt;Node.js&lt;/strong&gt;, curl, or your automation tool of choice.&lt;/p&gt;

&lt;p&gt;If you want to try the exact examples above, you can grab a free key (no credit card, no A2P registration) and read the full reference here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blooio.com/integrations/api" rel="noopener noreferrer"&gt;iMessage API overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.blooio.com/guides/send-imessage-api-nodejs" rel="noopener noreferrer"&gt;Send iMessage with Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.blooio.com/guides/send-imessage-api-python" rel="noopener noreferrer"&gt;Send iMessage with Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://app.blooio.com/signup" rel="noopener noreferrer"&gt;Start free →&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What are you building — a bot, a CRM integration, outbound? Drop it in the comments. 👇&lt;/p&gt;

</description>
      <category>imessages</category>
      <category>ios</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>SMS Pumping Is Draining Your 2FA Budget — and Mobile-Originated iMessage 2FA Fixes It</title>
      <dc:creator>David Harvey</dc:creator>
      <pubDate>Sun, 28 Jun 2026 03:36:47 +0000</pubDate>
      <link>https://dev.to/blooio-messages/sms-pumping-is-draining-your-2fa-budget-and-mobile-originated-imessage-2fa-fixes-it-51lo</link>
      <guid>https://dev.to/blooio-messages/sms-pumping-is-draining-your-2fa-budget-and-mobile-originated-imessage-2fa-fixes-it-51lo</guid>
      <description>&lt;p&gt;If you send SMS one-time codes, there's a decent chance you're paying scammers to phone-spam themselves on your dime. It even has a name: &lt;strong&gt;SMS pumping&lt;/strong&gt;. And it's not a rounding error — Elon Musk claimed Twitter was losing &lt;strong&gt;~$60M/year&lt;/strong&gt; to fake 2FA traffic before they killed SMS 2FA for free accounts.&lt;/p&gt;

&lt;p&gt;Here's how the scam works, why SMS 2FA is &lt;em&gt;structurally&lt;/em&gt; expensive, and why flipping the direction — &lt;strong&gt;mobile-originated (MO) 2FA&lt;/strong&gt;, taken to its logical end over iMessage — fixes both the cost and the fraud at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SMS pumping?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SMS pumping&lt;/strong&gt; (also called &lt;strong&gt;AIT — Artificially Inflated Traffic&lt;/strong&gt;, or &lt;strong&gt;SMS toll fraud&lt;/strong&gt;) is a scheme where bad actors abuse a form that sends SMS one-time codes. They pump thousands of phone numbers — usually premium ranges they secretly control with a telecom — into your "send me a code" endpoint.&lt;/p&gt;

&lt;p&gt;You pay for every one of those messages. A cut of that termination fee flows back to the fraudsters via the carrier. The "users" never log in. They were never users. The entire point was to make your verification endpoint dial a meter that pays them.&lt;/p&gt;

&lt;p&gt;The structure that makes this possible is simple: &lt;strong&gt;you, the company, send (and pay for) the message.&lt;/strong&gt; Every code is revenue for someone in the delivery chain — so there's a direct financial incentive to trigger as many as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why SMS 2FA is expensive even without fraud
&lt;/h2&gt;

&lt;p&gt;Even with zero abuse, application-to-person (&lt;strong&gt;A2P SMS&lt;/strong&gt;) is a bad cost curve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You pay per message.&lt;/strong&gt; Volume spikes — a launch, a bot attack, an international audience — turn into surprise bills.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;International is brutal.&lt;/strong&gt; Cross-border A2P carries steep carrier surcharges that vary wildly by destination.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Carrier fees and registration overhead.&lt;/strong&gt; In the US you're funneled through A2P 10DLC registration, brand vetting, and per-segment fees before you send a single legit code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So your 2FA line item is &lt;em&gt;pay-per-event&lt;/em&gt;, &lt;em&gt;unpredictable&lt;/em&gt;, and &lt;em&gt;exploitable&lt;/em&gt;. Three bad properties for something that's supposed to be boring infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Twitter/X case
&lt;/h2&gt;

&lt;p&gt;This isn't theoretical. When X announced it was removing SMS 2FA for non-paying users, the stated reason was fraud at scale:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.govinfosecurity.com/twitter-to-charge-for-sms-second-factor-authentication-a-21247" rel="noopener noreferrer"&gt;Musk: Twitter was scammed ~$60M/yr by fake 2FA SMS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techeconomy.ng/commentary-elon-musk-says-twitter-lost-60mn-a-year-to-bot-accounts-used-by-390-telcos-to-pump-a2p-sms/" rel="noopener noreferrer"&gt;~390 telcos implicated in pumping A2P SMS to inflate traffic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A company that size could "fix" it by paywalling a security feature. Most teams can't — and shouldn't have to make 2FA a paid tier just to dodge a billing exploit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: flip the direction (mobile-originated 2FA)
&lt;/h2&gt;

&lt;p&gt;Here's the key insight. SMS pumping only works because &lt;strong&gt;the company sends the message&lt;/strong&gt;. That outbound, pay-per-code flow is the thing being gamed.&lt;/p&gt;

&lt;p&gt;So flip it. In &lt;strong&gt;mobile-originated (MO) 2FA&lt;/strong&gt;, the &lt;em&gt;user&lt;/em&gt; sends a message &lt;em&gt;to you&lt;/em&gt; to prove possession of their device. There's no outbound code to pump, no per-message payout to harvest, and nothing for a bot farm to monetize. The incentive that powers the entire scam disappears.&lt;/p&gt;

&lt;p&gt;MO verification has been around (think shortcodes), but shortcodes are clunky, region-locked, and still cost money to provision. The modern version is much nicer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking it further: reverse 2FA over iMessage
&lt;/h2&gt;

&lt;p&gt;We built a live demo of this. Instead of &lt;em&gt;us&lt;/em&gt; texting &lt;em&gt;you&lt;/em&gt; a code to type back, &lt;strong&gt;you text a one-time code to us from your own iMessage&lt;/strong&gt; — and we verify you the instant the message lands.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://demo.blooio.com/2fa" rel="noopener noreferrer"&gt;demo.blooio.com/2fa&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your app generates a short one-time code and a deep link that opens Messages with that code pre-filled.&lt;/li&gt;
&lt;li&gt;The user hits send from &lt;strong&gt;their&lt;/strong&gt; iMessage.&lt;/li&gt;
&lt;li&gt;Blooio delivers an inbound &lt;code&gt;message.received&lt;/code&gt; webhook. You match the code and read who sent it — verified.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because the user sends from their own Apple ID over end-to-end-encrypted iMessage, it's &lt;strong&gt;spoof-resistant&lt;/strong&gt; (unlike trivially-faked SMS sender IDs) and &lt;strong&gt;phishing-resistant&lt;/strong&gt; (the user proves real possession instead of reading digits back to an attacker). And there's no outbound message to pump.&lt;/p&gt;

&lt;h3&gt;
  
  
  The code is almost embarrassingly small
&lt;/h3&gt;

&lt;p&gt;Start a challenge, then let a webhook flip it to verified:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. Start a challenge: generate a code + an iMessage deep link&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/2fa/start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;newCode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// short, unambiguous one-time code&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// status: "pending"&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// opens Messages to your Blooio number with the code pre-filled&lt;/span&gt;
    &lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://start.msg.new/&amp;lt;your-handle&amp;gt;?text=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Blooio calls your webhook when the user texts the code in&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/webhook/blooio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message.received&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extractCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// event.sender is the verified identifier (phone/email)&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the whole trick: no outbound SMS, no per-code billing, no A2P registration. Just an inbound webhook and a string match.&lt;/p&gt;

&lt;h2&gt;
  
  
  SMS 2FA vs. reverse iMessage 2FA
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Reverse iMessage 2FA&lt;/th&gt;
&lt;th&gt;Traditional SMS 2FA&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pricing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Flat monthly rate, predictable&lt;/td&gt;
&lt;td&gt;Pay per message — spikes = surprise bills&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Abuse&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Can't be pumped (users message &lt;em&gt;you&lt;/em&gt;)&lt;/td&gt;
&lt;td&gt;Wide open to SMS pumping / AIT fraud&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost at scale&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cheap, especially cross-border&lt;/td&gt;
&lt;td&gt;Steep international + carrier surcharges&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;E2E encrypted, tied to Apple ID&lt;/td&gt;
&lt;td&gt;Sender IDs spoofable; SIM-swap exposure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Anti-phishing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;User proves real possession&lt;/td&gt;
&lt;td&gt;Codes get phished or relayed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Instant over WiFi/data&lt;/td&gt;
&lt;td&gt;Often delayed, sometimes never delivered&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How this actually saves you money
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Predictable cost, not pay-per-event.&lt;/strong&gt; A flat rate means a bot storm can't author your invoice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fraud incentive removed.&lt;/strong&gt; No outbound code = nothing to pump = the $60M-style leak can't happen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No A2P 10DLC / DUNS / carrier registration tax&lt;/strong&gt; to start sending.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cheaper internationally&lt;/strong&gt;, where SMS surcharges hurt the most.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it / build it
&lt;/h2&gt;

&lt;p&gt;Play with the live reverse-2FA demo: &lt;strong&gt;&lt;a href="https://demo.blooio.com/2fa" rel="noopener noreferrer"&gt;demo.blooio.com/2fa&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want to build it into your own auth flow, &lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;Blooio&lt;/a&gt; is an iMessage API for developers — REST API, webhooks, and SDKs. &lt;strong&gt;Start free — no credit card, no A2P registration, no DUNS.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>googlesheets</category>
      <category>imessages</category>
      <category>ios</category>
    </item>
    <item>
      <title>How to Check if a Phone Number is Registered with iMessage Using Google Sheets and the Blooio API</title>
      <dc:creator>David Harvey</dc:creator>
      <pubDate>Sun, 22 Feb 2026 04:38:57 +0000</pubDate>
      <link>https://dev.to/blooio/how-to-check-if-a-phone-number-is-registered-with-imessage-using-google-sheets-and-the-blooio-api-3b75</link>
      <guid>https://dev.to/blooio/how-to-check-if-a-phone-number-is-registered-with-imessage-using-google-sheets-and-the-blooio-api-3b75</guid>
      <description>&lt;p&gt;For sales, marketing, and outreach teams, knowing whether a prospect uses &lt;strong&gt;iMessage&lt;/strong&gt; or standard SMS is a game-changer. Delivering a "blue bubble" message gives you access to read receipts, typing indicators, high-quality media sharing, and generally higher engagement rates — features that simply don't exist with regular SMS.&lt;/p&gt;

&lt;p&gt;But how do you check if a phone number is registered with iMessage across a list of hundreds of contacts without manually typing them into your iPhone?&lt;/p&gt;

&lt;p&gt;In this tutorial, you'll learn how to build a custom &lt;a href="https://sheets.new" rel="noopener noreferrer"&gt;Google Sheets&lt;/a&gt; function using &lt;strong&gt;&lt;a href="https://developers.google.com/apps-script" rel="noopener noreferrer"&gt;Google Apps Script&lt;/a&gt;&lt;/strong&gt; and the &lt;strong&gt;&lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;Blooio API&lt;/a&gt;&lt;/strong&gt; to automatically detect iMessage availability for any phone number or Apple ID email — at scale.&lt;/p&gt;

&lt;p&gt;By the end of this guide, you'll be able to type &lt;code&gt;=CHECKIMESSAGE(A2)&lt;/code&gt; into any cell and instantly know if that contact is iMessage-ready.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why iMessage Detection Matters for Sales and Marketing
&lt;/h2&gt;

&lt;p&gt;Understanding whether your prospects are on iMessage vs. SMS isn't just a nice-to-have — it directly impacts your outreach strategy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;iMessage users&lt;/strong&gt; get rich media, read receipts, and higher open rates — ideal for high-touch B2B sales.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SMS fallback&lt;/strong&gt; is universal and works for everyone else.&lt;/li&gt;
&lt;li&gt;Routing messages correctly reduces costs and increases deliverability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is especially powerful when combined with a tool like &lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;Blooio&lt;/a&gt;, a cloud-hosted messaging API that bridges automation platforms and native Apple iMessage — letting you send and receive iMessages programmatically without needing a physical Mac or iPhone constantly active.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you start, make sure you have the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A &lt;strong&gt;Google account&lt;/strong&gt; (for &lt;a href="https://sheets.new" rel="noopener noreferrer"&gt;Google Sheets&lt;/a&gt; and &lt;a href="https://developers.google.com/apps-script" rel="noopener noreferrer"&gt;Google Apps Script&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;A list of &lt;strong&gt;phone numbers or Apple ID emails&lt;/strong&gt; to check.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;&lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;Blooio account&lt;/a&gt;&lt;/strong&gt; and API Key — you can grab your key from the &lt;a href="https://app.blooio.com" rel="noopener noreferrer"&gt;Blooio dashboard&lt;/a&gt;. &lt;em&gt;(Blooio is a cloud-hosted messaging API that bridges the gap between automation tools and native Apple iMessage.)&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 1: Set Up Your Google Sheet
&lt;/h2&gt;

&lt;p&gt;Head to &lt;a href="https://sheets.new" rel="noopener noreferrer"&gt;sheets.new&lt;/a&gt; to instantly create a new Google Sheet. Add a column of phone numbers in &lt;strong&gt;Column A&lt;/strong&gt; and label &lt;strong&gt;Column B&lt;/strong&gt; as "iMessage Status".&lt;/p&gt;

&lt;p&gt;Don't worry if your numbers are formatted messily (e.g., with dashes, spaces, or country codes) — our script will normalize them automatically into the E.164 format that APIs prefer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2z6gvjqlm9cusccl6uz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2z6gvjqlm9cusccl6uz.png" alt="screenshot of a simple Google Sheet with a " width="800" height="855"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Open Google Apps Script
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developers.google.com/apps-script" rel="noopener noreferrer"&gt;Google Apps Script&lt;/a&gt; is a JavaScript-based cloud scripting platform that lets you extend Google Workspace products like Sheets, Docs, and Gmail. It supports &lt;a href="https://developers.google.com/apps-script/guides/sheets/functions" rel="noopener noreferrer"&gt;custom functions in Google Sheets&lt;/a&gt; — meaning you can write your own formulas just like &lt;code&gt;=SUM()&lt;/code&gt; or &lt;code&gt;=VLOOKUP()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;From your Google Sheet, navigate to the top menu and click:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extensions &amp;gt; Apps Script&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This opens a new browser tab with the Apps Script editor. Clear any default code in the &lt;code&gt;Code.gs&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6gfqs9raxrv1t1kzsi53.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6gfqs9raxrv1t1kzsi53.png" alt="screenshot of the blank Google Apps Script editor window" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Add the Blooio iMessage Detection Code
&lt;/h2&gt;

&lt;p&gt;Copy and paste the following JavaScript into your Apps Script editor.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Replace &lt;code&gt;'YOUR_BLOOIO_API_KEY_HERE'&lt;/code&gt; with your actual Blooio API key, which you can find in your &lt;a href="https://app.blooio.com" rel="noopener noreferrer"&gt;Blooio dashboard&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Normalize a US phone number string to E.164 (+1XXXXXXXXXX).
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;normalizeToE164US&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Already E.164 format&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\+&lt;/span&gt;&lt;span class="sr"&gt;1&lt;/span&gt;&lt;span class="se"&gt;\d{10}&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Remove extensions like ext.123, x123, #123&lt;/span&gt;
  &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;ext&lt;/span&gt;&lt;span class="se"&gt;\.?&lt;/span&gt;&lt;span class="sr"&gt;|x|#&lt;/span&gt;&lt;span class="se"&gt;)\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*$/i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Remove non-digits&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;digits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\D&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Handle 10 or 11-digit US numbers&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Handle something like "+1 707 653 2043"&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;plusDigits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\+&lt;/span&gt;&lt;span class="sr"&gt;1&lt;/span&gt;&lt;span class="se"&gt;\d{10}&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;plusDigits&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;plusDigits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Calls the Blooio API and returns if iMessage is available.
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchImessageAvailability_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_BLOOIO_API_KEY_HERE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Replace with your actual key from https://app.blooio.com&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://backend.blooio.com/v1/api/contacts/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/capabilities&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bearer &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;muteHttpExceptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;UrlFetchApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getResponseCode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContentText&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;imessage&lt;/span&gt;
        &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iMessage available&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iMessage not available&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Not Found&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;API Error: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; - &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Request Failed: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Custom Google Sheets function to check if a phone number or email is registered with iMessage.
 *
 * Example: =CHECKIMESSAGE(A2)
 *
 * @param {string} contact Phone number or Apple ID email.
 * @return {string} "iMessage available" / "iMessage not available" / error message.
 * @customfunction
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;CHECKIMESSAGE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Handle Apple ID email addresses directly&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetchImessageAvailability_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Normalize phone numbers to E.164&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;e164&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalizeToE164US&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;e164&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error: Couldn't parse as a US phone number or email.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetchImessageAvailability_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e164&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once pasted, click the &lt;strong&gt;Save&lt;/strong&gt; icon (the floppy disk) or press &lt;code&gt;Cmd+S&lt;/code&gt; / &lt;code&gt;Ctrl+S&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Test Your New Custom Function
&lt;/h2&gt;

&lt;p&gt;Head back to your Google Sheet. In cell &lt;strong&gt;B2&lt;/strong&gt;, type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=CHECKIMESSAGE(A2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hit &lt;strong&gt;Enter&lt;/strong&gt;. The cell will briefly show &lt;code&gt;Loading...&lt;/code&gt; while it calls the Blooio API, then return one of these results:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;iMessage available&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The number/email is registered with iMessage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;iMessage not available&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The contact uses standard SMS (Android or SMS-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Not Found&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The number isn't recognized&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Error: ...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A parsing or network issue occurred&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Once it works for one cell, drag the formula down column B to enrich your entire list in seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxo0fj8jyyfd1za5mzhas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxo0fj8jyyfd1za5mzhas.png" alt="iMessages status of every number in Google Sheets" width="800" height="855"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Works Under the Hood
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Phone Number Normalization
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;normalizeToE164US()&lt;/code&gt; function cleans up messy CRM data — stripping out extensions, dashes, spaces, and country code prefixes — converting everything into the standard &lt;strong&gt;E.164 format&lt;/strong&gt; (&lt;code&gt;+1XXXXXXXXXX&lt;/code&gt;) that REST APIs expect.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Blooio &lt;code&gt;/capabilities&lt;/code&gt; API Call
&lt;/h3&gt;

&lt;p&gt;The script calls &lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;Blooio's&lt;/a&gt; &lt;code&gt;/capabilities&lt;/code&gt; endpoint, passing either a normalized phone number or an Apple ID email address. This is the same endpoint used by Blooio's messaging infrastructure to determine how to route a message before sending it.&lt;/p&gt;

&lt;p&gt;You can explore &lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;Blooio's full pricing and feature set&lt;/a&gt; to understand what else is possible — including programmatic iMessage sending, read receipt tracking, and SMS fallback.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Response Parsing
&lt;/h3&gt;

&lt;p&gt;The script checks the &lt;code&gt;capabilities.imessage&lt;/code&gt; boolean in the JSON response and converts it to a human-readable label (&lt;code&gt;"iMessage available"&lt;/code&gt; or &lt;code&gt;"iMessage not available"&lt;/code&gt;) directly inside your spreadsheet cell.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scaling This Up: Tips for Large Lists
&lt;/h2&gt;

&lt;p&gt;If you're running this against thousands of rows, keep these &lt;a href="https://developers.google.com/apps-script/guides/sheets/functions#optimization" rel="noopener noreferrer"&gt;Google Apps Script best practices&lt;/a&gt; in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Batch API calls&lt;/strong&gt; — avoid calling the API on every cell individually; consider a trigger-based batch function instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache results&lt;/strong&gt; — use &lt;code&gt;CacheService&lt;/code&gt; to store results for numbers you've already checked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limiting&lt;/strong&gt; — respect API rate limits; add a &lt;code&gt;Utilities.sleep()&lt;/code&gt; call between requests for large batches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error handling&lt;/strong&gt; — the script already handles 404s and network failures gracefully, but log unexpected errors to a separate sheet for review.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;By connecting &lt;a href="https://sheets.new" rel="noopener noreferrer"&gt;Google Sheets&lt;/a&gt; and &lt;a href="https://developers.google.com/apps-script" rel="noopener noreferrer"&gt;Google Apps Script&lt;/a&gt; with the &lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;Blooio API&lt;/a&gt;, you've built a lightweight but powerful &lt;strong&gt;CRM enrichment tool&lt;/strong&gt; for iMessage detection.&lt;/p&gt;

&lt;p&gt;Sales teams can now confidently segment their outreach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send rich media, reactions, and read-receipt-enabled messages to &lt;strong&gt;iMessage users&lt;/strong&gt; via &lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;Blooio&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Fall back to standard A2P SMS for Android and non-Apple contacts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This kind of contact intelligence — knowing &lt;em&gt;before&lt;/em&gt; you send whether someone is reachable over iMessage — is a small automation that compounds into significantly better deliverability and engagement over time.&lt;/p&gt;

&lt;p&gt;Ready to get started? &lt;a href="https://app.blooio.com" rel="noopener noreferrer"&gt;Create your free Blooio account&lt;/a&gt; and grab your API key.&lt;/p&gt;




&lt;p&gt;Have you built any other automations around iMessage, RCS, or SMS routing? Drop a comment below — I'd love to see what you're building!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>imessages</category>
      <category>ios</category>
    </item>
    <item>
      <title>iMessage Group Chats in HighLevel: Native Integration Without Chrome Plugins</title>
      <dc:creator>David Harvey</dc:creator>
      <pubDate>Sun, 11 Jan 2026 09:04:54 +0000</pubDate>
      <link>https://dev.to/blooio/imessage-group-chats-in-highlevel-native-integration-without-chrome-plugins-4d54</link>
      <guid>https://dev.to/blooio/imessage-group-chats-in-highlevel-native-integration-without-chrome-plugins-4d54</guid>
      <description>&lt;h2&gt;
  
  
  Connect iMessage to HighLevel Workflows - No A2P or 10DLC Required
&lt;/h2&gt;

&lt;p&gt;HighLevel users can now create &lt;strong&gt;iMessage group chats directly from workflows&lt;/strong&gt; using &lt;a href="https://blooio.com/integrations/high-level" rel="noopener noreferrer"&gt;Blooio's native integration&lt;/a&gt;. Unlike traditional SMS that requires A2P registration and 10DLC compliance, iMessage group chats work instantly - and the best part? &lt;strong&gt;No Chrome plugin required&lt;/strong&gt;, making it fully compatible with the HighLevel mobile app (Lead Connector).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltq3wycb0n5a5kpdrgy3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltq3wycb0n5a5kpdrgy3.png" alt="iMessage Group Chats in HighLevel" width="800" height="664"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why iMessage for Business Communication?
&lt;/h2&gt;

&lt;p&gt;While SMS requires jumping through regulatory hoops with A2P and 10DLC registration, &lt;strong&gt;iMessage bypasses these restrictions entirely&lt;/strong&gt;. You can send messages programmatically through the iMessage API without carrier fees, registration delays, or compliance headaches.&lt;/p&gt;

&lt;p&gt;Compared to alternatives like SendBlue or Linq, &lt;a href="https://blooio.com/compare/blooio-vs-sendblue" rel="noopener noreferrer"&gt;Blooio offers native HighLevel integration&lt;/a&gt; with group chat support, making it the superior choice for agencies and SaaS platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  How iMessage Group Chats Work in HighLevel
&lt;/h2&gt;

&lt;p&gt;The integration is seamless and works across all HighLevel environments:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Trigger From Workflows&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Add the &lt;strong&gt;"Send Group Message"&lt;/strong&gt; action to any HighLevel workflow. Perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Buyer introductions (loop in multiple stakeholders)&lt;/li&gt;
&lt;li&gt;Customer onboarding (connect clients with support teams)&lt;/li&gt;
&lt;li&gt;Project kickoffs (bring together clients and account managers)&lt;/li&gt;
&lt;li&gt;Multi-party negotiations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Or Start Manually&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can also initiate group chats directly from the Conversations tab in HighLevel. No need to switch between tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Native Mobile App Support&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Because Blooio integrates natively into HighLevel (not via a Chrome extension), &lt;strong&gt;it works perfectly on the Lead Connector mobile app&lt;/strong&gt;. Respond to group messages on the go, just like any other conversation in HighLevel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases: iMessage API for Customer Support
&lt;/h2&gt;

&lt;p&gt;Here's how businesses are using iMessage group chats with HighLevel:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real Estate Agents&lt;/strong&gt;: Create a group with buyer, seller, and lender to streamline communication&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agencies&lt;/strong&gt;: Loop in clients with their account manager and specialist team members&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SaaS Onboarding&lt;/strong&gt;: Connect new customers with CSM, technical support, and billing in one thread&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E-commerce&lt;/strong&gt;: Create group chats between customers, fulfillment, and customer service&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up iMessage in HighLevel Workflows
&lt;/h2&gt;

&lt;p&gt;Getting started takes less than 5 minutes:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Connect Blooio
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Sign up at &lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;blooio.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Connect your Blooio account to HighLevel from &lt;a href="https://app.blooio.com" rel="noopener noreferrer"&gt;app.blooio.com&lt;/a&gt; under the integrations tab&lt;/li&gt;
&lt;li&gt;Get your API credentials from the &lt;a href="https://blooio.com/integrations/api" rel="noopener noreferrer"&gt;Blooio API dashboard&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Add to Workflow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open any HighLevel workflow&lt;/li&gt;
&lt;li&gt;Add the "Send Group Message" action&lt;/li&gt;
&lt;li&gt;Enter participant phone numbers or emails&lt;/li&gt;
&lt;li&gt;Customize your message&lt;/li&gt;
&lt;li&gt;Save and activate&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 3: Manage Conversations
&lt;/h3&gt;

&lt;p&gt;All group chat messages sync as contacts in HighLevel. Read and reply directly in the Conversations tab - no external apps needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  iMessage Automation: Beyond HighLevel
&lt;/h2&gt;

&lt;p&gt;Blooio's iMessage API works with more than just HighLevel:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;n8n Workflows&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Build custom &lt;a href="https://blooio.com/integrations/n8n" rel="noopener noreferrer"&gt;iMessage automation with n8n&lt;/a&gt;. Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blooio.com/integrations/n8n/workflows/emergency-imessages-bot" rel="noopener noreferrer"&gt;Emergency iMessage bot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://blooio.com/integrations/n8n/workflows/imessages-calorie-bot" rel="noopener noreferrer"&gt;Calorie tracking bot&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blooio.com/integrations/n8n/workflows/imessage-bot-example" rel="noopener noreferrer"&gt;AI chatbot with memory&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Make.com Integration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Connect iMessage to thousands of apps with &lt;a href="https://blooio.com/integrations/make" rel="noopener noreferrer"&gt;Blooio's Make integration&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Zapier Support&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use &lt;a href="https://blooio.com/integrations/zapier" rel="noopener noreferrer"&gt;Blooio with Zapier&lt;/a&gt; to automate iMessage without code.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Clay Integration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Send personalized iMessages at scale with &lt;a href="https://blooio.com/integrations/clay" rel="noopener noreferrer"&gt;Blooio + Clay&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building an iMessage Chatbot with AI
&lt;/h2&gt;

&lt;p&gt;Want to create an &lt;strong&gt;AI agent for iMessages&lt;/strong&gt;? Blooio's API makes it simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Receive webhooks&lt;/strong&gt; for incoming messages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send typing indicators&lt;/strong&gt; to show the bot is responding
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mark messages as read&lt;/strong&gt; programmatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send multiple messages&lt;/strong&gt; for natural conversation flow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://blooio.com/integrations/n8n/workflows/imessage-bot-example" rel="noopener noreferrer"&gt;iMessage bot example workflow&lt;/a&gt; shows how to build a conversational AI that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remembers conversation history (Postgres memory)&lt;/li&gt;
&lt;li&gt;Responds naturally (Claude AI)&lt;/li&gt;
&lt;li&gt;Splits responses into multiple texts&lt;/li&gt;
&lt;li&gt;Shows typing indicators&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  iMessage API vs SendBlue vs Linq
&lt;/h2&gt;

&lt;p&gt;Here's why developers are choosing Blooio:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Blooio&lt;/th&gt;
&lt;th&gt;SendBlue&lt;/th&gt;
&lt;th&gt;Linq&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HighLevel Native Integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Group Chat Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ beta&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Works on Mobile App&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes (no plugin)&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Read Receipts API&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Typing Indicators API&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;n8n Integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Make.com Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Migration Assistance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Send to Email Addresses&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Receive from Email Addresses&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;See the full comparison: &lt;a href="https://blooio.com/compare/blooio-vs-sendblue" rel="noopener noreferrer"&gt;Blooio vs SendBlue&lt;/a&gt; or &lt;a href="https://blooio.com/compare/blooio-vs-linq-blue" rel="noopener noreferrer"&gt;Blooio vs Linq&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Switching from Linq? Check out the &lt;a href="https://blooio.com/migrate/linq" rel="noopener noreferrer"&gt;Linq migration guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Send Messages Without A2P or 10DLC
&lt;/h2&gt;

&lt;p&gt;One of the biggest advantages of using iMessage for business:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No A2P registration required&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;No 10DLC compliance needed&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;No carrier fees&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;No message limits&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;No registration delays&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;While SMS requires weeks of registration, spending limits, and ongoing compliance, iMessage works immediately. This makes it perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time-sensitive communications&lt;/li&gt;
&lt;li&gt;International messaging&lt;/li&gt;
&lt;li&gt;High-volume sending&lt;/li&gt;
&lt;li&gt;Personal relationship building&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Broadcast Messages with iMessage
&lt;/h2&gt;

&lt;p&gt;Need to send bulk iMessages? Blooio's developer API supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Personalized mass messaging&lt;/strong&gt; via Clay or n8n&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scheduled broadcasts&lt;/strong&gt; through workflows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drip campaigns&lt;/strong&gt; with HighLevel automation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event-triggered messages&lt;/strong&gt; based on user actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike SMS where broadcast messages often get filtered or blocked, iMessages land in the primary inbox with full rich media support.&lt;/p&gt;

&lt;h2&gt;
  
  
  iMessage Developer API Documentation
&lt;/h2&gt;

&lt;p&gt;Ready to build? Here's what you can do with Blooio's API:&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Endpoints
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /v1/api/messages - Send iMessage
POST /v1/api/read/{id} - Mark as read
POST /v1/api/typing/{id} - Show typing
DELETE /v1/api/typing/{id} - Hide typing
GET /v1/api/messages - List messages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Webhook Events
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;message.received&lt;/code&gt; - New message&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;message.sent&lt;/code&gt; - Message delivered
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;message.read&lt;/code&gt; - Read receipt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Full documentation: &lt;a href="https://blooio.com/integrations/api" rel="noopener noreferrer"&gt;Blooio API Docs&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Apple Messages API Alternative
&lt;/h2&gt;

&lt;p&gt;While Apple doesn't officially offer a public iMessage API, Blooio provides a production-ready alternative that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Works with existing Apple infrastructure&lt;/li&gt;
&lt;li&gt;Requires no reverse engineering&lt;/li&gt;
&lt;li&gt;Maintains message security and encryption&lt;/li&gt;
&lt;li&gt;Scales to enterprise needs&lt;/li&gt;
&lt;li&gt;Includes developer support&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  iMessage for SaaS Platforms
&lt;/h2&gt;

&lt;p&gt;SaaS companies are using Blooio to:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Embed iMessage into products&lt;/strong&gt; - White-label messaging without building infrastructure&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customer onboarding&lt;/strong&gt; - Text users directly during signup flows&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Support conversations&lt;/strong&gt; - Handle &lt;a href="https://blooio.com/integrations/freshdesk" rel="noopener noreferrer"&gt;iMessage customer support&lt;/a&gt; tickets&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transactional messages&lt;/strong&gt; - Order confirmations, shipping updates, account alerts&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product notifications&lt;/strong&gt; - Feature announcements, usage alerts, renewal reminders&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with iMessage in HighLevel
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sign up for Blooio&lt;/strong&gt;: &lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;blooio.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connect to HighLevel&lt;/strong&gt;: &lt;a href="https://blooio.com/integrations/high-level" rel="noopener noreferrer"&gt;Integration guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create your first group chat&lt;/strong&gt;: Add "Send Group Message" to a workflow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test on mobile&lt;/strong&gt;: Download Lead Connector and see it work without Chrome&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Pricing &amp;amp; Partners
&lt;/h2&gt;

&lt;p&gt;Blooio offers transparent pricing for all use cases. If you're a HighLevel agency or reseller, check out the &lt;a href="https://blooio.com/partners" rel="noopener noreferrer"&gt;Blooio Partners Program&lt;/a&gt; for exclusive benefits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: Do I need A2P registration for iMessage?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
No. iMessage bypasses SMS regulations entirely. No A2P, no 10DLC, no compliance headaches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Will this work on the Lead Connector mobile app?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Yes! Because Blooio integrates natively (not via Chrome plugin), it works perfectly on mobile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can I send attachments in group chats?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Yes. iMessage supports images, videos, documents, and more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How does this compare to SendBlue?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Blooio offers native HighLevel integration, group chat support, and works on mobile apps. See the &lt;a href="https://blooio.com/compare/blooio-vs-sendblue" rel="noopener noreferrer"&gt;full comparison&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can I build an AI chatbot with this?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Absolutely. Check out the &lt;a href="https://blooio.com/integrations/n8n" rel="noopener noreferrer"&gt;iMessage bot examples&lt;/a&gt; for inspiration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Is there a limit to group chat participants?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Follows standard iMessage limits (typically 32 participants).&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Blooio continues to expand iMessage capabilities for business users:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MCP (Model Context Protocol) integration&lt;/strong&gt; - &lt;a href="https://blooio.com/integrations/mcp" rel="noopener noreferrer"&gt;Check it out&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Whop marketplace support&lt;/strong&gt; - &lt;a href="https://blooio.com/integrations/whop" rel="noopener noreferrer"&gt;Learn more&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced analytics&lt;/strong&gt; - Message delivery tracking and insights&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Additional automation platforms&lt;/strong&gt; - More integrations on the way&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stay updated with the &lt;a href="https://blooio.com/feature-log" rel="noopener noreferrer"&gt;Blooio feature log&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start Using iMessage Group Chats Today
&lt;/h2&gt;

&lt;p&gt;Stop juggling multiple apps and Chrome plugins. &lt;strong&gt;Unify all your HighLevel communications&lt;/strong&gt; with native iMessage support that works everywhere - desktop, mobile, and web.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try Blooio today&lt;/strong&gt;: &lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;blooio.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connect to HighLevel&lt;/strong&gt;: &lt;a href="https://blooio.com/integrations/high-level" rel="noopener noreferrer"&gt;Integration guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Need help?&lt;/strong&gt; Check the &lt;a href="https://blooio.com/privacy-policy" rel="noopener noreferrer"&gt;privacy policy&lt;/a&gt; and &lt;a href="https://blooio.com/terms-of-service" rel="noopener noreferrer"&gt;terms of service&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Built for developers, loved by agencies.&lt;/strong&gt; Blooio makes iMessage programmable.&lt;/p&gt;

</description>
      <category>highlevel</category>
      <category>imessage</category>
      <category>automation</category>
      <category>api</category>
    </item>
    <item>
      <title>Build Your Own iMessage AI Bot in Minutes with blooio</title>
      <dc:creator>David Harvey</dc:creator>
      <pubDate>Sat, 10 Jan 2026 12:30:05 +0000</pubDate>
      <link>https://dev.to/blooio/build-your-own-imessage-ai-bot-in-minutes-with-msgnew-26b3</link>
      <guid>https://dev.to/blooio/build-your-own-imessage-ai-bot-in-minutes-with-msgnew-26b3</guid>
      <description>&lt;h2&gt;
  
  
  Try msg.new - Then Build Your Own
&lt;/h2&gt;

&lt;p&gt;Want to see what's possible? Text &lt;a href="https://msg.new" rel="noopener noreferrer"&gt;msg.new&lt;/a&gt; right now and chat with an AI via iMessage. It responds like a real person—complete with typing indicators, read receipts, and natural multi-message replies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;msg.new is a proof of concept we built to showcase what you can create with Blooio.&lt;/strong&gt; The entire workflow is open source, running on n8n, so you can deploy your own iMessage bot in minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Build iMessage Bots with Blooio?
&lt;/h2&gt;

&lt;p&gt;Building iMessage bots has traditionally been complex and locked behind Apple's ecosystem. &lt;strong&gt;Blooio changes that with a REST API for iMessage.&lt;/strong&gt; With Blooio and this n8n workflow, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deploy in minutes&lt;/strong&gt;: Import the workflow, add your API keys, and you're live&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full iMessage features&lt;/strong&gt;: Read receipts, typing indicators, attachments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-powered&lt;/strong&gt;: Uses Claude for natural conversations with memory&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open source workflow&lt;/strong&gt;: Customize every part of the bot's behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How the msg.new Workflow Works
&lt;/h2&gt;

&lt;p&gt;The workflow powering msg.new is elegantly simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Webhook&lt;/strong&gt; receives incoming iMessages from Blooio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event filter&lt;/strong&gt; checks for &lt;code&gt;message.received&lt;/code&gt; events&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attachment check&lt;/strong&gt; routes text vs image messages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural delay&lt;/strong&gt; adds realistic response timing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read receipt&lt;/strong&gt; marks the message as read via Blooio API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typing indicator&lt;/strong&gt; shows the bot is "typing" via Blooio API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Agent&lt;/strong&gt; generates responses using Claude + Postgres chat memory&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message splitting&lt;/strong&gt; breaks responses into natural, short messages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loop&lt;/strong&gt; sends each message separately via Blooio API for authentic texting feel&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Conversational AI with Memory
&lt;/h3&gt;

&lt;p&gt;The bot uses Postgres to store conversation history, so it remembers previous exchanges. This is powered by the n8n Postgres Chat Memory node connected to Claude.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Message Responses
&lt;/h3&gt;

&lt;p&gt;Real people don't send wall-of-text messages. The workflow splits AI responses into multiple shorter messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Split by newline and remove empty lines&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aiOutput&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Each line becomes a separate message&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Natural Texting Behavior
&lt;/h3&gt;

&lt;p&gt;The system prompt instructs Claude to text like a casual human:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Short, 1-3 sentence messages&lt;/li&gt;
&lt;li&gt;Lowercase, minimal punctuation&lt;/li&gt;
&lt;li&gt;Authentic reactions and occasional humor&lt;/li&gt;
&lt;li&gt;No corporate speak or over-explaining&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Full iMessage Integration via Blooio
&lt;/h3&gt;

&lt;p&gt;Using Blooio's API endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;POST /v1/api/read/{external_id}&lt;/code&gt; - Send read receipts&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /v1/api/typing/{external_id}&lt;/code&gt; - Show typing indicator&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DELETE /v1/api/typing/{external_id}&lt;/code&gt; - Hide typing indicator
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /v1/api/messages&lt;/code&gt; - Send messages&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Build Your Own iMessage Bot
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Try msg.new First
&lt;/h3&gt;

&lt;p&gt;Visit &lt;a href="https://msg.new" rel="noopener noreferrer"&gt;https://msg.new&lt;/a&gt; and text the bot to see what's possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Get the Workflow
&lt;/h3&gt;

&lt;p&gt;Full code and setup instructions: &lt;a href="https://blooio.com/integrations/n8n/workflows/imessage-bot-example" rel="noopener noreferrer"&gt;https://blooio.com/integrations/n8n/workflows/imessage-bot-example&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. What You'll Need
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A Blooio account&lt;/strong&gt; (for the iMessage API) - &lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;Sign up here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;n8n instance (cloud or self-hosted)&lt;/li&gt;
&lt;li&gt;Anthropic API key (for Claude)&lt;/li&gt;
&lt;li&gt;Postgres database (for chat memory)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Quick Setup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Sign up for Blooio and get your API token&lt;/li&gt;
&lt;li&gt;Import the workflow JSON into n8n&lt;/li&gt;
&lt;li&gt;Add your Blooio API token to the HTTP Request nodes&lt;/li&gt;
&lt;li&gt;Configure your Postgres credentials in the Chat Memory node&lt;/li&gt;
&lt;li&gt;Add your Anthropic API key&lt;/li&gt;
&lt;li&gt;Activate the workflow&lt;/li&gt;
&lt;li&gt;Set the webhook URL in your Blooio dashboard&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Customization Ideas
&lt;/h2&gt;

&lt;p&gt;The open-source nature means you can modify anything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Change the personality&lt;/strong&gt;: Edit the system prompt to make your bot formal, funny, or professional&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add tools&lt;/strong&gt;: Connect the AI Agent to other services (weather, calendar, databases)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle attachments&lt;/strong&gt;: The workflow already detects attachments—add image analysis with vision models&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response timing&lt;/strong&gt;: Adjust the Wait node duration for faster/slower replies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message splitting logic&lt;/strong&gt;: Modify the Code node to control how responses are broken up&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Technical Highlights
&lt;/h2&gt;

&lt;p&gt;The workflow uses several advanced n8n features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI Agent with memory&lt;/strong&gt;: Maintains conversation context across sessions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split in Batches&lt;/strong&gt;: Loops through messages to send them sequentially&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP Request nodes&lt;/strong&gt;: Direct API integration with Blooio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conditional routing&lt;/strong&gt;: Handles different event types and message formats&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code node&lt;/strong&gt;: Custom JavaScript for message processing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Blooio?
&lt;/h2&gt;

&lt;p&gt;Blooio provides a REST API for iMessage, letting you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send and receive iMessages programmatically&lt;/li&gt;
&lt;li&gt;Access read receipts and typing indicators&lt;/li&gt;
&lt;li&gt;Handle attachments (images, videos, files)&lt;/li&gt;
&lt;li&gt;Scale to multiple phone numbers&lt;/li&gt;
&lt;li&gt;Get webhooks for real-time message events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;No need to reverse-engineer Apple protocols or maintain Mac infrastructure.&lt;/strong&gt; Blooio handles the complexity so you can focus on building your bot's features.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Can Build
&lt;/h2&gt;

&lt;p&gt;This workflow is just the beginning. With Blooio, you can create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customer service bots&lt;/li&gt;
&lt;li&gt;Personal AI assistants&lt;/li&gt;
&lt;li&gt;Automated notifications and alerts&lt;/li&gt;
&lt;li&gt;Two-way communication systems&lt;/li&gt;
&lt;li&gt;Integration with existing business tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The combination of Blooio + n8n + AI makes iMessage automation accessible to developers without deep iOS knowledge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started Today
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Try msg.new&lt;/strong&gt; to see a live example: &lt;a href="https://msg.new" rel="noopener noreferrer"&gt;https://msg.new&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get the workflow&lt;/strong&gt;: &lt;a href="https://blooio.com/integrations/n8n/workflows/imessage-bot-example" rel="noopener noreferrer"&gt;https://blooio.com/integrations/n8n/workflows/imessage-bot-example&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sign up for Blooio&lt;/strong&gt;: &lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;https://blooio.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The entire setup takes less than 10 minutes if you have your API keys ready. Start building your iMessage bot today!&lt;/p&gt;

&lt;p&gt;Have you built any iMessage automations? What would you use this for? Drop a comment below!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>n8n</category>
      <category>automation</category>
      <category>imessage</category>
    </item>
    <item>
      <title>iMessage Enrichment in Clay: Boost Your Outreach with Real-Time Contact Detection</title>
      <dc:creator>David Harvey</dc:creator>
      <pubDate>Thu, 25 Dec 2025 22:37:41 +0000</pubDate>
      <link>https://dev.to/blooio/imessage-enrichment-in-clay-boost-your-outreach-with-real-time-contact-detection-1ick</link>
      <guid>https://dev.to/blooio/imessage-enrichment-in-clay-boost-your-outreach-with-real-time-contact-detection-1ick</guid>
      <description>&lt;p&gt;If you're doing outreach in 2026, you already know that not all communication channels are created equal. But did you know that &lt;strong&gt;iMessage has a 98% open rate&lt;/strong&gt; compared to SMS's 20-30%? That's a game-changer for sales, marketing, and customer success teams.&lt;/p&gt;

&lt;p&gt;The catch? You need to know which contacts actually support iMessage before you reach out. Enter &lt;strong&gt;iMessage enrichment&lt;/strong&gt; – and today, I'm excited to share that Blooio now integrates directly with Clay to make this incredibly simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is iMessage Enrichment?
&lt;/h2&gt;

&lt;p&gt;iMessage enrichment is the process of checking whether a phone number or email address is registered with Apple's iMessage service. This lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prioritize high-engagement channels&lt;/strong&gt; (iMessage has 45% higher response rates)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Segment your outreach&lt;/strong&gt; based on messaging capabilities
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improve lead scoring&lt;/strong&gt; with real-time contact validation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automate workflow routing&lt;/strong&gt; based on iMessage availability&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Matters for Clay Users
&lt;/h2&gt;

&lt;p&gt;Clay is the go-to platform for data enrichment and outreach automation. But until now, checking iMessage availability required custom API calls or manual verification. &lt;/p&gt;

&lt;p&gt;With &lt;a href="https://blooio.com/integrations/clay" rel="noopener noreferrer"&gt;Blooio's new Clay integration&lt;/a&gt;, you can now:&lt;/p&gt;

&lt;p&gt;✅ Check iMessage availability directly in your Clay tables&lt;br&gt;
✅ Enrich phone numbers AND email addresses&lt;br&gt;&lt;br&gt;
✅ Get instant, real-time detection&lt;br&gt;
✅ Use a ready-made template (no setup required)&lt;/p&gt;
&lt;h2&gt;
  
  
  How to Set Up iMessage Enrichment in Clay
&lt;/h2&gt;

&lt;p&gt;It takes just 3 steps:&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: Add the Blooio Template
&lt;/h3&gt;

&lt;p&gt;Search for "Blooio" in Clay's enrichment templates and add it to your table. Connect it with your Blooio API key (get one free at &lt;a href="https://app.blooio.com" rel="noopener noreferrer"&gt;app.blooio.com&lt;/a&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2: Select Your Contact Data
&lt;/h3&gt;

&lt;p&gt;Choose which column contains phone numbers or emails. Blooio will check each contact for iMessage availability.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 3: Get Enriched Results
&lt;/h3&gt;

&lt;p&gt;Instantly see which contacts support iMessage. Use this data to segment and prioritize your outreach.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4m5a7tltblna3x4pbb9b.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4m5a7tltblna3x4pbb9b.gif" alt="Blooio Clay Integration Demo" width="782" height="800"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  API Response Example
&lt;/h2&gt;

&lt;p&gt;Here's what you get back from the Blooio API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"contact"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+1234567890"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"capabilities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"imessage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lastChecked"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2024-01-01T00:00:00.000Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also check email addresses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"contact"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"capabilities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"imessage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lastChecked"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2024-01-01T00:00:00.000Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Sales Outreach Prioritization
&lt;/h3&gt;

&lt;p&gt;Identify iMessage-enabled prospects and route them to high-touch sequences. These contacts convert 3x better due to personal device engagement.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Marketing Campaign Segmentation
&lt;/h3&gt;

&lt;p&gt;Create separate campaigns for iMessage vs. SMS contacts. Leverage the "blue bubble advantage" for maximum engagement.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Customer Success Optimization
&lt;/h3&gt;

&lt;p&gt;Reach customers on their preferred channel. iMessage-enabled contacts respond 72% faster to support messages.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Lead Scoring Enhancement
&lt;/h3&gt;

&lt;p&gt;Add iMessage availability as a lead scoring factor. It's a strong indicator of contact quality and reachability.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Data Quality Validation
&lt;/h3&gt;

&lt;p&gt;Validate phone numbers while enriching. Know which numbers are active and reachable through Apple's network.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;Blooio's iMessage enrichment API is available on all plans starting at $89/month. Enterprise plans include unlimited enrichment checks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blooio.com/integrations/clay" rel="noopener noreferrer"&gt;Learn more about Blooio's Clay integration →&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;Ready to supercharge your Clay workflows with iMessage enrichment?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get your free Blooio API key at &lt;a href="https://app.blooio.com" rel="noopener noreferrer"&gt;app.blooio.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Search for "Blooio" in Clay's enrichment templates&lt;/li&gt;
&lt;li&gt;Start enriching your contact data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Check out the &lt;a href="https://docs.blooio.com/" rel="noopener noreferrer"&gt;full documentation&lt;/a&gt; or &lt;a href="https://blooio.com/integrations/clay" rel="noopener noreferrer"&gt;explore the integration page&lt;/a&gt; to learn more.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;About Blooio&lt;/strong&gt;: Blooio is a Communications Platform as a Service (CPaaS) that enables businesses to send iMessages, RCS, and make calls. Our mission is to help teams reach their contacts on the channels that drive the best engagement.&lt;/p&gt;

</description>
      <category>imessage</category>
      <category>enrichment</category>
      <category>clay</category>
      <category>api</category>
    </item>
    <item>
      <title>Build a Receipt Parser AI Bot with Blooio, n8n, Claude &amp; Google Sheets</title>
      <dc:creator>David Harvey</dc:creator>
      <pubDate>Mon, 08 Dec 2025 05:36:39 +0000</pubDate>
      <link>https://dev.to/blooio/build-a-receipt-parser-ai-bot-with-blooio-n8n-claude-google-sheets-4gme</link>
      <guid>https://dev.to/blooio/build-a-receipt-parser-ai-bot-with-blooio-n8n-claude-google-sheets-4gme</guid>
      <description>&lt;p&gt;Imagine this: every time someone finishes a purchase, they snap a photo of the receipt and text it to your number. A few seconds later, all the key fields—merchant, date, total, tax, category, payment method—show up in a Google Sheet, ready for bookkeeping or expense dashboards.&lt;/p&gt;

&lt;p&gt;In this tutorial, you'll build exactly that: a "text-a-receipt" AI bot that uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blooio Messaging&lt;/strong&gt; with a pre-warmed iMessage number&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;n8n's Blooio node&lt;/strong&gt; to receive incoming messages and images&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude AI&lt;/strong&gt; (with "parse binary images" enabled) to extract receipt data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Sheets node&lt;/strong&gt; to log structured JSON data automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;You'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;Blooio account&lt;/strong&gt; and API key from &lt;a href="https://app.blooio.com" rel="noopener noreferrer"&gt;app.blooio.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;At least one &lt;strong&gt;pre-warmed number&lt;/strong&gt; in Blooio (Blooio shows how many pre-warmed numbers are available on &lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;blooio.com&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;n8n instance&lt;/strong&gt; (Cloud or self-hosted)&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Google account&lt;/strong&gt; with access to Google Sheets&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;Anthropic API key&lt;/strong&gt; for Claude from the &lt;a href="https://console.anthropic.com" rel="noopener noreferrer"&gt;Anthropic console&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: Set Up Blooio and Your Pre-Warmed Number
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://app.blooio.com" rel="noopener noreferrer"&gt;app.blooio.com&lt;/a&gt; and create a new organization if you don't have one yet.&lt;/li&gt;
&lt;li&gt;On the home/dashboard page, note the number of &lt;strong&gt;pre-warmed numbers&lt;/strong&gt; available. As of writing, there are 3 pre-warmed numbers ready for testing and small production pilots.&lt;/li&gt;
&lt;li&gt;In the Blooio app, generate an &lt;strong&gt;API key&lt;/strong&gt; and store it somewhere safe—you'll paste this into n8n as credentials.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point, you're ready to send and receive iMessages/texts through Blooio programmatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Create the Google Sheet for Receipts
&lt;/h2&gt;

&lt;p&gt;Create a new Google Sheet called something like &lt;code&gt;Receipt Log (AI Bot)&lt;/code&gt; with these columns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Timestamp&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;From&lt;/strong&gt; (phone/contact)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Merchant&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Date&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tax&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Currency&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Category&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Payment Method&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Raw JSON&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can adapt this schema to your needs, but this structure works well for bookkeeping and analytics.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Connect n8n to Blooio (Incoming Messages)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Log into your n8n instance.&lt;/li&gt;
&lt;li&gt;Install or enable the &lt;strong&gt;Blooio Messaging&lt;/strong&gt; integration if it isn't already available in your nodes list. You can find it at &lt;a href="https://n8n.io/integrations/blooio-messaging" rel="noopener noreferrer"&gt;n8n.io/integrations/blooio-messaging&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;new workflow&lt;/strong&gt; and add the Blooio trigger/node that listens for incoming messages (typically exposed as a webhook-style trigger).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the Blooio dashboard, point your chosen pre-warmed iMessage number to the n8n webhook URL so that every incoming text or image to that number triggers your workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test it:&lt;/strong&gt; Send yourself a text and a photo of a receipt to confirm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The workflow is triggered&lt;/li&gt;
&lt;li&gt;The incoming message includes binary data for images&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 4: Configure the AI Node (Claude with Parse Binary Images)
&lt;/h2&gt;

&lt;p&gt;Now let's parse the receipt image with Claude via the n8n AI node.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add an &lt;strong&gt;AI node&lt;/strong&gt; after your Blooio trigger.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Claude&lt;/strong&gt; as the provider and plug in your Anthropic API key from &lt;a href="https://console.anthropic.com" rel="noopener noreferrer"&gt;console.anthropic.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;"parse binary images"&lt;/strong&gt; in the AI node so the model can see the receipt image directly from the incoming Blooio message.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Claude Prompt for Receipt Parsing
&lt;/h3&gt;

&lt;p&gt;Use this as the &lt;strong&gt;system/instruction prompt&lt;/strong&gt; in your AI node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a precise receipt parser.

Input: a photo of a receipt sent by a user.

Task: Extract clean, structured data from the receipt and return **valid JSON only**, no prose.

JSON schema (all fields required, use null if missing):

{
  "merchant": "string",
  "purchase_date": "YYYY-MM-DD",
  "purchase_time": "HH:MM or null",
  "total_amount": "number",
  "subtotal_amount": "number or null",
  "tax_amount": "number or null",
  "currency": "3-letter ISO code or null",
  "payment_method": "string (e.g. VISA, Mastercard, Cash, Amex, Apple Pay)",
  "line_items": [
    {
      "description": "string",
      "quantity": "number or null",
      "unit_price": "number or null",
      "line_total": "number or null",
      "category": "string (e.g. groceries, restaurant, transport, software, utilities, other)"
    }
  ],
  "notes": "string with any extra comments, discounts, tips, or ambiguity notes"
}

Rules:
- Never include explanations, markdown, or commentary.
- If multiple totals exist (e.g. with tip), choose the **final amount charged** as total_amount.
- Normalize dates to YYYY-MM-DD even if the receipt uses another format.
- If you are unsure, make your best guess and add an explanation to the notes field.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the AI node, map the incoming &lt;strong&gt;binary image data&lt;/strong&gt; from the Blooio node as the image input so Claude can see the receipt image.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Map AI Output to Google Sheets
&lt;/h2&gt;

&lt;p&gt;After the AI node, add a &lt;strong&gt;Set node&lt;/strong&gt; (or Code node if you prefer) to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parse the JSON returned by Claude&lt;/li&gt;
&lt;li&gt;Flatten/map it to match your Google Sheets columns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, you might map:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Timestamp&lt;/code&gt; → &lt;code&gt;{{$now}}&lt;/code&gt; or the message timestamp from Blooio&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;From&lt;/code&gt; → sender phone number from Blooio's payload&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Merchant&lt;/code&gt; → &lt;code&gt;{{$json["merchant"]}}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Date&lt;/code&gt; → &lt;code&gt;{{$json["purchase_date"]}}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Total&lt;/code&gt; → &lt;code&gt;{{$json["total_amount"]}}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Tax&lt;/code&gt; → &lt;code&gt;{{$json["tax_amount"]}}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Currency&lt;/code&gt; → &lt;code&gt;{{$json["currency"]}}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Payment Method&lt;/code&gt; → &lt;code&gt;{{$json["payment_method"]}}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Raw JSON&lt;/code&gt; → full stringified JSON from the AI node (handy for debugging)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;strong&gt;Google Sheets&lt;/strong&gt; node, choose &lt;strong&gt;Append&lt;/strong&gt; or &lt;strong&gt;Add Row&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Authenticate with your Google account.&lt;/li&gt;
&lt;li&gt;Select the spreadsheet and worksheet you created in Step 2.&lt;/li&gt;
&lt;li&gt;Map each field from the Set node to the correct column in the sheet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Run the workflow with &lt;strong&gt;test data&lt;/strong&gt; (e.g. send a new receipt photo) and verify that a new row appears in your sheet with all fields populated.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Optional Enhancements
&lt;/h2&gt;

&lt;p&gt;Once the basic flow works, consider adding:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validation &amp;amp; Fallback:&lt;/strong&gt; If Claude returns invalid JSON, route the message to a human-review channel or a separate "Errors" sheet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auto-Categorization Rules:&lt;/strong&gt; Post-process the &lt;code&gt;category&lt;/code&gt; field with your own rules or another AI call, then update the row in Sheets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reply Back via Blooio:&lt;/strong&gt; Add a Blooio send node at the end to confirm: &lt;em&gt;"Got your receipt from {merchant} for {total}. Logged to your expense sheet."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This turns your workflow into a full loop: user sends a receipt, AI parses, data is stored, and the user gets instant confirmation via iMessage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Useful Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blooio Messaging Dashboard&lt;/strong&gt; (get your API key, pre-warmed numbers): &lt;a href="https://app.blooio.com" rel="noopener noreferrer"&gt;app.blooio.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blooio + n8n Integration&lt;/strong&gt;: &lt;a href="https://n8n.io/integrations/blooio-messaging" rel="noopener noreferrer"&gt;n8n.io/integrations/blooio-messaging&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blooio Home&lt;/strong&gt;: &lt;a href="https://blooio.com" rel="noopener noreferrer"&gt;blooio.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;n8n Automation Platform&lt;/strong&gt;: &lt;a href="https://n8n.io" rel="noopener noreferrer"&gt;n8n.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anthropic Console&lt;/strong&gt; (Claude API key): &lt;a href="https://console.anthropic.com" rel="noopener noreferrer"&gt;console.anthropic.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;You've just built an AI-powered receipt parser that turns text messages into structured expense data—no backend coding required. This same pattern works for invoices, business cards, handwritten notes, and more.&lt;/p&gt;

&lt;p&gt;What will you automate next with Blooio and n8n? Drop a comment below with your ideas!&lt;/p&gt;

</description>
      <category>n8n</category>
      <category>ai</category>
      <category>automation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Automate iMessage at Scale with the Blooio API: Direct Integration Guide</title>
      <dc:creator>David Harvey</dc:creator>
      <pubDate>Fri, 14 Nov 2025 05:14:07 +0000</pubDate>
      <link>https://dev.to/blooio/automate-imessage-at-scale-with-the-blooio-api-direct-integration-guide-19jj</link>
      <guid>https://dev.to/blooio/automate-imessage-at-scale-with-the-blooio-api-direct-integration-guide-19jj</guid>
      <description>&lt;h2&gt;
  
  
  Why iMessage Automation Is a Game Changer
&lt;/h2&gt;

&lt;p&gt;If you want &lt;strong&gt;sky-high open rates, instant trust, and rich customer communication&lt;/strong&gt;, iMessage is unbeatable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;2x higher open rates&lt;/strong&gt; than SMS&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Blue bubble&lt;/em&gt; creates trust with US customers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;90% of iPhone users&lt;/strong&gt; prefer iMessage&lt;/li&gt;
&lt;li&gt;Images, videos, reactions—&lt;strong&gt;rich media support&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yet, &lt;strong&gt;Apple offers no official API&lt;/strong&gt;. Most automation guides rely on hacks or third-party services. &lt;strong&gt;Blooio&lt;/strong&gt; solves this the right way: using &lt;strong&gt;actual iPhones&lt;/strong&gt; as hardware bridges and exposes a true HTTP REST API for direct automation.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Blooio Works: Core Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Your App / Workflow]
      ↓  (HTTP API)
[Blooio API]
      ↓
[Physical Apple Devices]
      ↓
[iMessage Network]
      ↓
[Customer's iPhone]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No extra scripts, browser emulators, or unreliable hacks. Just send an API request; Blooio delivers your iMessage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Started: Blooio API
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Blooio account (free trial, no CC required)&lt;/li&gt;
&lt;li&gt;API key from your dashboard&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The API
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Sending a Message
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Endpoint:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;POST https://backend.blooio.com/v1/api/messages&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Headers:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Idempotency-Key: unique-id-123 (optional - prevents duplicates)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Request Body Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+15551234567"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;recipient&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;E.&lt;/span&gt;&lt;span class="mi"&gt;164&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;format&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello from Blooio API!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;message&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"attachments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/img.png"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;array&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;media&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;URLs&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"ticketid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TCK-123"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;optional&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tracking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;info&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What Happens:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your message is queued for delivery.&lt;/li&gt;
&lt;li&gt;Attachments (image, video) are sent if URLs provided.&lt;/li&gt;
&lt;li&gt;All metadata tracked for your own analytics.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Response
&lt;/h4&gt;

&lt;p&gt;For duplicates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"messageid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Qm8FhbH3P7R"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"queued"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If new, status code is &lt;code&gt;202 Accepted&lt;/code&gt; and same response payload.&lt;/p&gt;




&lt;h3&gt;
  
  
  Key Endpoints
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/v1/api/messages&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Send new iMessage/SMS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/v1/api/messages?limit=100&amp;amp;sort=desc&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List messages (filterable by contact/status/date)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/v1/api/messages/{messageId}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get message details/status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/v1/api/messages/{messageId}/status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get delivery status only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;/v1/api/messages/{messageId}&lt;/code&gt; (DELETE)&lt;/td&gt;
&lt;td&gt;Cancel a queued message&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/v1/api/contacts/{contact}/capabilities&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check contact's iMessage/SMS support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/v1/api/webhooks&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Manage webhook URLs for delivery events (sent/failed/delivered)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Webhooks for Incoming &amp;amp; Status
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Register a webhook (e.g., on your backend): &lt;code&gt;/v1/api/webhooks&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Get real-time POSTs for events like:

&lt;ul&gt;
&lt;li&gt;message.received (inbound from customer)&lt;/li&gt;
&lt;li&gt;message.sent, delivered, failed, read&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Payloads include all message content, contact, status, timestamps.&lt;/p&gt;




&lt;h3&gt;
  
  
  Example: Send a Message from Python
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://backend.blooio.com/v1/api/messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Bearer YOUR_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;+15551234567&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Welcome to Blooio direct API!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Support Chatbot:&lt;/strong&gt; Receive iMessages via webhook, send to AI, reply back instantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Appointment Reminders:&lt;/strong&gt; Trigger via Google Calendar API, send iMessage with details using Blooio API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Order Updates:&lt;/strong&gt; Connect your backend (Shopify, Woo) and notify with delivery info.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All flows integrate natively via HTTP, but you can still use Make.com, Zapier, or n8n for visual orchestration if preferred—just use their HTTP module to talk to Blooio API.&lt;/p&gt;




&lt;h2&gt;
  
  
  Error Handling &amp;amp; Validation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use the response codes and webhook status.&lt;/li&gt;
&lt;li&gt;Validate recipient formats: use E.164 (&lt;code&gt;+1XXXXXXXXXX&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Implement idempotency with &lt;code&gt;Idempotency-Key&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Rate limits: ~100+ messages/min via Apple hardware.&lt;/li&gt;
&lt;li&gt;You can always fallback to SMS using Blooio, or another SMS provider if recipient is not an iPhone user.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Store API keys securely, never hardcode!&lt;/p&gt;




&lt;h2&gt;
  
  
  Advanced Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Check device/account status:&lt;/strong&gt; &lt;code&gt;/v1/api/me&lt;/code&gt; for plan/devices/usage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contact capability lookup:&lt;/strong&gt; &lt;code&gt;/v1/api/contacts/{contact}/capabilities&lt;/code&gt;
Find if target supports iMessage, SMS, RCS, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch sending:&lt;/strong&gt; 
Bulk endpoints are available (stubbed for now).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Integration with No-Code Tools
&lt;/h2&gt;

&lt;p&gt;While this guide focuses on direct API usage, you can always plug Blooio into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Make.com:&lt;/strong&gt; Use HTTP module to POST directly to Blooio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;n8n:&lt;/strong&gt; Free and open source. Use HTTP Node.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zapier:&lt;/strong&gt; Connect via webhook.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.make.com/en/integrations/blooio" rel="noopener noreferrer"&gt;Official Make app.&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://zapier.com/apps/blooio/integrations" rel="noopener noreferrer"&gt;Official Zapier app.&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This lets you use drag-and-drop automation but leverages Blooio's direct messaging API for reliability and scale.&lt;/p&gt;




&lt;h2&gt;
  
  
  Useful References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.blooio.com" rel="noopener noreferrer"&gt;Blooio API documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://app.blooio.com/" rel="noopener noreferrer"&gt;Blooio's dashboard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/E.164" rel="noopener noreferrer"&gt;E.164 Format Standard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blooio.com/integrations" rel="noopener noreferrer"&gt;Blooio integrations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Have questions or want to see more examples? Drop them in the comments!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This guide spotlights direct Blooio API capabilities, minimizing reliance on third-party automation suites. Plug in your workflow, code, or favorite automation builder—Blooio handles iMessage delivery with real devices and simple REST endpoints.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>api</category>
      <category>tutorial</category>
      <category>nocode</category>
    </item>
  </channel>
</rss>
