← Back to Plugins
Channels

Telnyx Openclaw Sms Channel

team-telnyx By team-telnyx 👁 28 views ▲ 0 votes

OpenClaw channel plugin: SMS/MMS via Telnyx Messaging API

GitHub

Install

npm install
npm

Configuration Example

{
  "channels": {
    "telnyx-sms": {
      "apiKey": "KEY...",
      "allowFrom": ["+15551234567"],
      "exposure": {
        "publicUrl": "https://agent.example.com/telnyx-sms/webhook"
      }
    }
  }
}

README

# Telnyx SMS/MMS Channel for OpenClaw

Official Telnyx SMS plugin for OpenClaw. Give any OpenClaw agent a real Telnyx phone number so people can text the agent directly over SMS/MMS.

This package is the Telnyx-owned channel plugin for OpenClaw. It is designed around a one-key Telnyx setup path: paste a Telnyx API key, let the plugin discover the phone number, messaging profile, and webhook public key, then let it configure the messaging profile webhook safely.

## Why this plugin

- Official Telnyx-maintained OpenClaw SMS/MMS channel.
- One-key setup path using a Telnyx API v2 key.
- Auto-discovers the Telnyx phone number, messaging profile, and Ed25519 public key when possible.
- Automatically registers the OpenClaw webhook route.
- Can PATCH the Telnyx messaging profile webhook URL for you.
- Refuses to overwrite an existing third-party webhook unless explicitly allowed.
- Self-probes the public webhook URL to confirm it reaches this OpenClaw gateway.
- Runs a watchdog to detect tunnel or Telnyx profile webhook drift.
- Supports inbound SMS/MMS, outbound SMS/MMS, allowlisted access, and multi-account setups.

## Telnyx-native setup

This plugin is built for the official Telnyx path:

- Start with a single Telnyx API v2 key.
- Discover the Telnyx number, messaging profile, and webhook public key automatically when possible.
- Configure the Telnyx Messaging Profile webhook URL from OpenClaw.
- Protect existing webhook URLs by default.
- Confirm the public webhook URL reaches this OpenClaw gateway before using it.
- Watch for tunnel or webhook drift after setup.

## Features

- Inbound SMS through Telnyx Messaging webhooks.
- Inbound MMS payload parsing and delivery to OpenClaw.
- Outbound SMS replies through `POST /v2/messages`.
- Outbound MMS with `media_urls`.
- Ed25519 webhook signature verification using Telnyx webhook headers.
- OpenClaw direct-message threading by phone number.
- Optional pairing via SMS verification code.
- `allowlist` or `open` DM security mode.
- Outbound allowlist enforcement so an allowlisted bot cannot accidentally send to unknown numbers.
- Multi-account config for multiple Telnyx numbers/profiles from one OpenClaw instance.
- Automatic public key discovery from `GET /v2/public_key`.
- Automatic number/profile discovery from Telnyx phone-number APIs.
- Optional messaging profile creation and orphan-number attachment with explicit opt-in.
- Automatic webhook configuration with safe overwrite protection.
- Public URL self-probe and periodic webhook watchdog.
- In-memory status/event log for recent inbound, outbound, blocked, and error events.
- MMS media URL safety checks to prevent SSRF-style fetch risks.

## Prerequisites

- OpenClaw `2026.4.21` or later.
- A Telnyx account.
- A Telnyx API v2 key.
- A Telnyx phone number with SMS/MMS capability.
- A publicly reachable webhook URL for inbound SMS/MMS.
- For US A2P messaging, approved 10DLC brand/campaign setup in Telnyx.

## Install

From ClawHub:

```sh
clawhub package install telnyx-openclaw-sms-channel
```

From source while developing:

```sh
git clone https://github.com/team-telnyx/telnyx-openclaw-sms-channel.git
cd telnyx-openclaw-sms-channel
npm install
npm run build
```

## Quick start

### 1. Create a Telnyx API key

In the Telnyx Mission Control Portal:

1. Go to API Keys.
2. Create or copy an API v2 key.
3. Keep it private. It should start with `KEY...`.

### 2. Make sure you have an SMS-capable Telnyx number

The plugin can discover your number automatically, but the account still needs at least one SMS/MMS-capable number.

If the number is already attached to a Messaging Profile, the plugin can reuse that profile. If the number is not attached to a profile, set `autoCreateProfile: true` only when you want the plugin to create a profile and attach the orphan number for you.

### 3. Configure OpenClaw

Minimal config:

```json
{
  "channels": {
    "telnyx-sms": {
      "apiKey": "KEY...",
      "allowFrom": ["+15551234567"],
      "exposure": {
        "publicUrl": "https://agent.example.com/telnyx-sms/webhook"
      }
    }
  }
}
```

With only `apiKey`, the plugin attempts to discover:

- `defaultFromNumber`
- `messagingProfileId`
- `publicKey`

The `publicKey` is the Telnyx account-wide Ed25519 webhook public key from `GET /v2/public_key`.

### 4. Start OpenClaw

When the gateway starts, the plugin:

1. Registers the local webhook route, default `/telnyx-sms/webhook`.
2. Discovers missing Telnyx defaults when possible.
3. Resolves the public webhook URL.
4. Self-probes the public URL.
5. Configures the Telnyx Messaging Profile webhook URL if safe.
6. Starts a watchdog for route/profile drift.
7. Acknowledges validated webhooks quickly with `200 OK` so Telnyx does not retry unnecessarily.

### 5. Text the Telnyx number

If `dmSecurity` is `allowlist`, the sender must be in `allowFrom`.

If `dmSecurity` is `open`, anyone who knows the number can message the agent.

## Configuration reference

Full single-account example:

```json
{
  "channels": {
    "telnyx-sms": {
      "apiKey": "KEY...",
      "defaultFromNumber": "+15551234567",
      "messagingProfileId": "40000000-0000-0000-0000-000000000000",
      "publicKey": "base64-ed25519-public-key",
      "dmSecurity": "allowlist",
      "allowFrom": ["+15557654321"],
      "webhookPath": "/telnyx-sms/webhook",
      "exposure": {
        "publicUrl": "https://agent.example.com/telnyx-sms/webhook"
      },
      "overwriteExistingWebhook": false,
      "profileName": "OpenClaw Agent",
      "autoCreateProfile": false
    }
  }
}
```

### `apiKey`

Telnyx API v2 key. Required.

### `defaultFromNumber`

E.164 Telnyx number used for outbound SMS/MMS. Optional when discovery can find a number.

### `messagingProfileId`

Telnyx Messaging Profile ID. Optional when discovery can find the profile attached to `defaultFromNumber`.

### `publicKey`

Base64 Ed25519 public key used to verify Telnyx webhooks. Optional when discovery can fetch it from `GET /v2/public_key`.

### `dmSecurity`

Inbound/outbound DM security policy.

Allowed values:

- `allowlist`, default. Only numbers in `allowFrom` can message the bot. Outbound sends are also restricted to `allowFrom`.
- `open`. Any phone number can message the bot.

### `allowFrom`

Phone numbers allowed to message the bot when `dmSecurity` is `allowlist`.

```json
"allowFrom": ["+15551234567", "+15557654321"]
```

### `webhookPath`

Local OpenClaw route for Telnyx webhooks.

Default:

```json
"/telnyx-sms/webhook"
```

### `exposure.publicUrl`

Stable public URL that Telnyx should call.

```json
{
  "exposure": {
    "publicUrl": "https://agent.example.com/telnyx-sms/webhook"
  }
}
```

### `exposure.tunnel`

Development tunnel option when supported by the local machine.

```json
{
  "exposure": {
    "tunnel": { "provider": "cloudflared" }
  }
}
```

or:

```json
{
  "exposure": {
    "tunnel": { "provider": "ngrok" }
  }
}
```

### `overwriteExistingWebhook`

Default: `false`.

When false, the plugin refuses to overwrite a Telnyx Messaging Profile webhook URL that points somewhere else. This protects existing Zapier, production, or customer integrations.

Set to `true` only when you intentionally want this OpenClaw gateway to own the profile webhook.

### `profileName`

Name to use when auto-creating a Messaging Profile.

Default is derived from OpenClaw agent or instance metadata.

### `autoCreateProfile`

Default: `false`.

When true, the plugin may create a Messaging Profile and attach an orphan Telnyx number if no profile exists. This is explicit opt-in because profile/number changes are visible in the Telnyx dashboard and may affect billing or routing.

## Multi-account setup

Use `accounts` when one OpenClaw instance should serve multiple Telnyx numbers/profiles.

```json
{
  "channels": {
    "telnyx-sms": {
      "apiKey": "KEY-default",
      "allowFrom": ["+15550000001"],
      "accounts": {
        "support": {
          "apiKey": "KEY-support",
          "defaultFromNumber": "+15551230000",
          "messagingProfileId": "support-profile-id",
          "allowFrom": ["+15557654321"]
        },
        "sales": {
          "apiKey": "KEY-sales",
          "defaultFromNumber": "+15551230001",
          "messagingProfileId": "sales-profile-id",
          "dmSecurity": "open"
        }
      }
    }
  }
}
```

## Architecture

The plugin has four main parts:

1. **OpenClaw channel plugin**
   - Registers the `telnyx-sms` channel with OpenClaw.
   - Handles outbound delivery for SMS/MMS.
   - Exposes channel capabilities, setup flow, pairing, and account resolution.

2. **Telnyx Messaging API client**
   - Sends SMS/MMS through `POST https://api.telnyx.com/v2/messages`.
   - Uses the configured or discovered Telnyx phone number as `from`.
   - Includes `messaging_profile_id` when available.
   - Adds `media_urls` for MMS delivery.

3. **Inbound webhook handler**
   - Registers an HTTP route in the OpenClaw gateway.
   - Default route: `/telnyx-sms/webhook`.
   - Reads the raw request body.
   - Verifies Telnyx Ed25519 webhook signatures.
   - Parses inbound SMS/MMS payloads.
   - Dispatches messages into OpenClaw as direct conversations.

4. **Setup and watchdog layer**
   - Discovers phone number, messaging profile, and webhook public key from Telnyx.
   - Resolves the public webhook URL.
   - Optionally configures the Telnyx Messaging Profile webhook URL.
   - Self-probes the public URL to confirm traffic reaches this gateway.
   - Re-checks routing/profile state periodically and logs drift.

5. **Diagnostics and media-safety layer**
   - Keeps a bounded in-memory event log of recent SMS activity.
   - Records inbound receives, outbound sends, blocked media, and dispatch errors.
   - Validates inbound MMS media URLs before allowing them into the message pipeline.
   - Rejects localhost, private IPs, metadata-service IPs, non-HTTPS URLs, and non-Telnyx media hosts.

```text
User phone
   │ SMS/MMS
   ▼
Telnyx Messaging
   

... (truncated)
channels

Comments

Sign in to leave a comment

Loading comments...