Skip to content

Channels

Beaco supports three delivery channels:

  • Email
  • SMS
  • Webhook

Each channel has its own recipient requirements, runtime configuration, and retry policy.

Channel Overview

Channel choice is declared per recipient via channels.

Example:

JSON
{
  "recipients": [
    {
      "channels": ["email", "sms"],
      "email": "[email protected]",
      "phone": "+15551234567"
    }
  ]
}

Beaco creates one notification per recipient-channel pair and routes each to the corresponding worker queue.

Email Channel

Email delivery is powered by Resend.

Recipient Requirements

For email channel, recipient must include:

  • email

Example recipient:

JSON
{
  "channels": ["email"],
  "email": "[email protected]"
}

Content Model

Email supports:

  • subject line
  • body content (plain text and/or HTML depending on template usage)

Sender and Reply-To

By default every email is sent from the server's configured sender address. You can pick a different sender per template or per inline email:

  • from_local is the part before the @ (for example orders). The domain always stays the server's verified domain, so a sender can never leave it.
  • from_name is the display name shown by mail clients.
  • reply_to is any valid email address and needs no DNS setup.
JSON
{
  "event_type": "order.confirmed",
  "recipients": [{ "channels": ["email"], "email": "[email protected]" }],
  "inline": {
    "subject": "Order BEA-1042 confirmed",
    "html": "<h1>Thanks for your order</h1>",
    "from_local": "orders",
    "from_name": "Winwell Orders",
    "reply_to": "[email protected]"
  }
}

This sends as Winwell Orders <orders@your-verified-domain> with replies going to [email protected]. When no field is set, the default sender is used. The same fields work on templates; see Templates.

Attachments

Add attachments: [{ "filename": "invoice.pdf", "url": "https://files.example.com/a.pdf", "size_bytes": 48213 }] to an event to attach files to its emails (up to 10, 30 MB declared in total). Beaco does not store the files: each url is downloaded at send time, by Resend or by Beaco's worker when SMTP is the provider, so it must be publicly reachable and stay reachable through retries.

Subject behavior:

  • Uses template subject when available.
  • Falls back to auto-generated subject when template subject is not defined.

Example Event (Email)

Bash
curl -X POST https://beaco.michaelogunjimi.com/api/v1/events \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_PROJECT_KEY" \
  -d '{
    "event_type": "password.reset",
    "recipients": [{
      "channels": ["email"],
      "email": "[email protected]"
    }],
    "payload": {
      "reset_url": "https://app.example.com/reset?token=abc"
    }
  }'

SMS Channel

SMS delivery is powered by Twilio.

Recipient Requirements

For sms channel, recipient must include:

  • phone in E.164 format

Valid example:

Text
+15551234567

Invalid examples:

  • 5551234567
  • +1 (555) 123-4567

Content Model

SMS supports:

  • plain text body only

SMS does not use a subject field.

Example Event (SMS)

Bash
curl -X POST https://beaco.michaelogunjimi.com/api/v1/events \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_PROJECT_KEY" \
  -d '{
    "event_type": "otp.sent",
    "recipients": [{
      "channels": ["sms"],
      "phone": "+15551234567"
    }],
    "payload": {
      "code": "093144"
    }
  }'

Webhook Channel

Webhook delivery sends a JSON payload to your destination URL.

Recipient Requirements

For webhook channel, recipient must include:

  • webhook_url

Example:

JSON
{
  "channels": ["webhook"],
  "webhook_url": "https://example.com/beaco/hooks"
}

Request Body Sent by Beaco

Webhook payload includes:

  • event_type
  • payload
  • notification_id
  • timestamp

Example webhook body:

JSON
{
  "event_type": "order.fulfilled",
  "payload": {
    "order_id": "ord_123"
  },
  "notification_id": "ntf_01j4za3vdy8r98t7b4s2v0x4bz",
  "timestamp": "2026-01-12T11:02:17Z"
}

URL Validation and SSRF Protection

Beaco validates webhook URLs before delivery:

  • must use http or https
  • hostname must resolve
  • private/internal IP destinations are blocked

This reduces SSRF risk and prevents delivery to internal network targets.

Example Event (Webhook)

Bash
curl -X POST https://beaco.michaelogunjimi.com/api/v1/events \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_PROJECT_KEY" \
  -d '{
    "event_type": "invoice.paid",
    "recipients": [{
      "channels": ["webhook"],
      "webhook_url": "https://example.com/hooks/invoices"
    }],
    "payload": {
      "invoice_id": "inv_10022"
    }
  }'

Channel Configuration

Each channel has configurable operational settings.

Common channel config fields:

FieldTypeDescription
enabledbooleanEnables or disables the channel
rate_limit_per_minuteintegerMax outbound sends per minute for channel

When a channel is disabled, Beaco skips new deliveries for that channel until re-enabled.

Rate limits help protect provider quotas and downstream systems.

Per-Channel Retry Policies

Retry behavior is configurable per channel.

Policy fields:

FieldDescription
max_retriesMaximum retry attempts before dead-letter
base_delay_secondsInitial backoff delay
max_backoff_secondsMaximum delay cap
jitterRandomized delay offset to spread retries

Example policy profile:

JSON
{
  "email": {
    "max_retries": 5,
    "base_delay_seconds": 10,
    "max_backoff_seconds": 600,
    "jitter": true
  },
  "sms": {
    "max_retries": 3,
    "base_delay_seconds": 5,
    "max_backoff_seconds": 120,
    "jitter": true
  },
  "webhook": {
    "max_retries": 8,
    "base_delay_seconds": 15,
    "max_backoff_seconds": 900,
    "jitter": true
  }
}

Choosing the Right Channel

Use this quick heuristic:

ScenarioRecommended Channel
User-facing transactional updatesEmail
Time-sensitive short alertsSMS
Service-to-service automationWebhook

You can combine channels for fallback or layered delivery.

Example strategy:

  • primary: email
  • urgent fallback: SMS
  • internal automation: webhook

Validation Summary

ChannelRequired Recipient FieldFormat Rules
EmailemailValid email syntax
SMSphoneE.164 (+15551234567)
Webhookwebhook_urlValid external http/https URL

Operational Tips

Keep channel-specific provider credentials and limits environment-specific (dev/staging/prod).

Use low retry counts for SMS cost control, and higher retry windows for webhook recovery workflows.

Monitor per-channel failure rates to detect provider incidents quickly.

  • Events for recipient schema and fan-out behavior.
  • Templates for channel-specific content rendering.
  • Delivery Pipeline for retries, DLQ, and suppression logic.
  • Quickstart to send your first channel-specific event.