Blooio API Reference

Rich link previews

Send URL messages with iMessage-style rich previews, override the image and title, and batch-send multiple links in one request

When a message's text is exactly a URL, Blooio delivers it as an iMessage URL balloon — the rounded bubble with a hero image, bold title, and link preview, the same shape that appears when a user pastes a URL into Messages.app.

Previews are generated automatically from the page's Open Graph metadata. Pass an optional link_preview object to override the image, the title, or both.

Auto-generated preview

Send a single URL and Blooio handles the rest — it fetches the page's OG tags and builds the preview.

curl -X POST 'https://backend.blooio.com/v2/api/chats/%2B15551234567/messages' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "https://example.com/launch"
  }'
const chatId = encodeURIComponent('+15551234567')
await fetch(`https://backend.blooio.com/v2/api/chats/${chatId}/messages`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.BLOOIO_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ text: 'https://example.com/launch' }),
})
import os, requests
from urllib.parse import quote

chat_id = quote('+15551234567', safe='')
requests.post(
f'https://backend.blooio.com/v2/api/chats/{chat_id}/messages',
headers={
'Authorization': f"Bearer {os.environ['BLOOIO_API_KEY']}",
'Content-Type': 'application/json',
},
json={'text': 'https://example.com/launch'},
)

Override the image and title

Pass a link_preview object with image_url, title, or both to replace what the auto-fetched preview would show.

curl -X POST 'https://backend.blooio.com/v2/api/chats/%2B15551234567/messages' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "https://example.com/launch",
    "link_preview": {
      "image_url": "https://cdn.example.com/previews/launch-hero.png",
      "title": "Our new product is here"
    }
  }'
await fetch(url, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    text: 'https://example.com/launch',
    link_preview: {
      image_url: 'https://cdn.example.com/previews/launch-hero.png',
      title: 'Our new product is here',
    },
  }),
})

Both fields inside link_preview are optional. If only title is provided, the image comes from auto-fetched OG metadata. If only image_url is provided, the title is auto-fetched.

Fields

FieldTypeDescription
image_urlstring (HTTPS URL)Points to an image (png, jpg, webp, or gif). Blooio downloads it server-side and attaches it as the bubble's hero. Maximum 16 MB.
titlestringBold title line shown in the bubble. Maximum 200 characters.

Batch — multiple URL messages in one request

Use the parts array and attach a link_preview to each part. Every part becomes its own URL-balloon message; messages are sent sequentially in the order of the array. The response contains message_ids and count instead of message_id.

curl -X POST 'https://backend.blooio.com/v2/api/chats/%2B15551234567/messages' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "parts": [
      {
        "text": "https://example.com/product",
        "link_preview": {
          "title": "Our product",
          "image_url": "https://cdn.example.com/previews/product.png"
        }
      },
      {
        "text": "https://example.com/pricing",
        "link_preview": { "title": "Pricing plans" }
      },
      {
        "text": "https://example.com/contact",
        "link_preview": {}
      }
    ]
  }'
await fetch(url, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    parts: [
      {
        text: 'https://example.com/product',
        link_preview: {
          title: 'Our product',
          image_url: 'https://cdn.example.com/previews/product.png',
        },
      },
      {
        text: 'https://example.com/pricing',
        link_preview: { title: 'Pricing plans' },
      },
      {
        text: 'https://example.com/contact',
        link_preview: {},
      },
    ],
  }),
})

Example response:

{
  "message_ids": ["msg_a1b2c3", "msg_d4e5f6", "msg_g7h8i9"],
  "status": "queued",
  "count": 3
}

In batch mode (any part with a link_preview), every part must be text-only and its text must be a single http(s) URL. Attachment parts and non-URL text are rejected with a 400.

Validation rules

  • link_preview requires the message text (or each per-part text) to be exactly a single http(s) URL — no surrounding words or whitespace. Mixed text plus URL returns 400.
  • Cannot be combined with the attachments field.
  • The single-message form doesn't accept an array of text values; use parts for batch mode.

Failure handling

Preview downloads are best-effort. If image_url can't be resolved (DNS error, 404, non-image content type, oversized file, or network timeout), the message still sends — Blooio silently falls back to the auto-fetched Open Graph preview. A broken preview URL never fails the request or returns 5xx.

What the recipient sees

The iMessage URL bubble on iPhone and iPad renders three elements:

  • Large hero image
  • Bold title line
  • URL host derived from the link

Any field you don't provide comes from the page's OG tags. Fields the iOS bubble doesn't render (site name, long description) aren't exposed here — only what the recipient actually sees.

Animated previews

If the target URL's Open Graph metadata points at an animated webp or mp4 (e.g. a video preview), Blooio delivers it as an animated bubble automatically — the same behavior you get pasting the URL into Messages.app's compose view. No extra parameters needed.

On this page