# How to Integrate Retool with Signal

- Tool: Retool
- Difficulty: Advanced
- Time required: 45 minutes
- Last updated: April 2026

## TL;DR

Connect Retool to Signal by deploying a self-hosted signal-cli-rest-api bridge container and adding it as a REST API Resource in Retool. Because Signal has no official public API, this approach uses the open-source signal-cli tool exposed as an HTTP server. Setup requires Docker and takes about 30-45 minutes. Use this pattern for privacy-sensitive internal alerts where Slack or email is not appropriate.

## Why Connect Retool to Signal?

Most Retool alerting integrations use Slack, Teams, or email — all of which are appropriate for routine operational notifications. But some alerts contain sensitive information that organizations want protected by end-to-end encryption: security incident notifications, compliance alerts containing PII, financial threshold warnings, or messages to executives about sensitive operational events. Signal's end-to-end encryption ensures that even your communication platform provider cannot read these messages, which is a meaningful security property for regulated industries.

Because Signal has no official public API, integration requires deploying signal-cli-rest-api — an open-source bridge project maintained by the community that runs as a Docker container on your infrastructure. This bridge registers a dedicated phone number with Signal's servers and exposes HTTP endpoints for sending messages and managing groups. Retool's REST API Resource connects to this bridge, which must be deployed on infrastructure that Retool's server-side proxy can reach — either within your VPC (for self-hosted Retool) or accessible via HTTPS with appropriate authentication (for Retool Cloud).

This integration is intentionally for advanced use cases. The complexity of deploying and maintaining a self-hosted Signal bridge is significantly higher than using Slack or Twilio for notifications. Choose Signal only when the end-to-end encryption property is genuinely required for your security policy — not as a default notification channel. For most operational alerts, Slack's native Retool connector or Twilio SMS provides appropriate security with significantly simpler setup.

## Before you start

- A phone number dedicated to sending Signal messages (a physical SIM, a VoIP number that receives SMS, or a Twilio number) — this becomes the Signal 'sender' identity for your organization
- Docker and Docker Compose available on a server your Retool instance can reach (a VPS, an EC2 instance, or a server within your VPC for self-hosted Retool)
- Basic familiarity with Docker container deployment and command-line operations for the one-time Signal registration step
- A Retool account (Cloud or self-hosted) with permission to add Resources
- A clear understanding of the security requirements that make Signal necessary — most alerting use cases are better served by Slack or Twilio

## Step-by-step guide

### 1. Deploy the signal-cli-rest-api Docker bridge

The signal-cli-rest-api project (github.com/bbernhard/signal-cli-rest-api) provides a Docker container that wraps signal-cli in an HTTP server. This is the only practical way to integrate Signal programmatically without an official API.

Deploy the container on a server accessible to your Retool instance. Create a docker-compose.yml file on the server with the following configuration. The container needs a persistent volume to store Signal registration data (keys and credentials) between restarts — losing this data requires re-registering the phone number, which involves a verification SMS.

Start the container with docker-compose up -d. The API server starts on port 8080 by default. Once running, you need to perform a one-time Signal registration for your dedicated phone number. Registration requires receiving an SMS or voice call at that number.

For Retool Cloud users, this server must be HTTPS-accessible from the internet. You can use a reverse proxy (nginx) with Let's Encrypt for TLS, or deploy behind a service like Cloudflare Tunnel. Add authentication (HTTP Basic Auth in the nginx config or the container's built-in auth) to protect the API from unauthorized access — unauthenticated Signal bridges have been abused for spam.

For self-hosted Retool users, the bridge can run within your private VPC without public internet exposure, which is the more secure architecture.

```
# docker-compose.yml for signal-cli-rest-api
# Deploy on your server, NOT in Retool
version: '3'
services:
  signal-cli-rest-api:
    image: bbernhard/signal-cli-rest-api:latest
    environment:
      - MODE=normal
      - PORT=8080
      # Optional: enable auto-receive for incoming messages
      - AUTO_RECEIVE_SCHEDULE=*/5 * * * *
    ports:
      - "8080:8080"
    volumes:
      # Persistent storage for Signal registration data — CRITICAL
      - ./signal-cli-config:/home/.local/share/signal-cli
    restart: unless-stopped
```

**Expected result:** The signal-cli-rest-api container is running and accessible on port 8080. The API responds to health check requests at GET /v1/health.

### 2. Register your Signal phone number via the CLI bridge

After the container is running, you must perform a one-time registration to link your dedicated phone number to Signal's servers. This step must be done via the signal-cli-rest-api HTTP endpoints — it cannot be done from the Retool interface because it requires an interactive verification step.

From your server or a machine that can reach the container, perform the registration:

Step 1: Send a registration request, which triggers Signal to send a verification SMS (or voice call) to your phone number. Use curl or any HTTP client to call the registration endpoint with your phone number in E.164 format (e.g., +15551234567).

Step 2: Receive the SMS verification code on your dedicated phone number.

Step 3: Submit the verification code to the verify endpoint. After successful verification, the bridge is registered and can send messages.

Step 4: Create a profile name for your organization's Signal sender — this appears as the contact name when recipients receive messages. Use a descriptive name like 'Ops Alerts' or 'Company Security Team'.

Note: Signal number registrations are tied to the data volume. If you delete the Docker volume without unregistering the number first, Signal will continue to associate the number with the old keys and you will need to re-register, which requires waiting for a new verification SMS. Always use docker-compose stop rather than deleting the container when maintaining the service.

```
# One-time registration commands
# Run these from a machine that can reach your signal-cli-rest-api container
# Replace +15551234567 with your actual phone number in E.164 format
# Replace BRIDGE_URL with your container's URL (e.g., http://localhost:8080)

# Step 1: Request SMS verification code
curl -X POST 'BRIDGE_URL/v1/register/+15551234567'
# For voice call verification: add ?voice=true to the URL

# Step 2: Verify with the code you received via SMS
# Replace 123456 with your actual verification code
curl -X POST 'BRIDGE_URL/v1/register/+15551234567/verify/123456'

# Step 3: Set a profile name for your organization's Signal identity
curl -X PUT 'BRIDGE_URL/v1/profiles/+15551234567' \
  -H 'Content-Type: application/json' \
  -d '{"name": "Ops Alerts"}'
```

**Expected result:** The phone number is successfully registered with Signal's servers through the bridge. You can verify by sending a test message to another Signal user via the bridge's send endpoint.

### 3. Add the signal-cli-rest-api as a Retool REST API Resource

With the bridge running and registered, configure Retool to communicate with it. Navigate to the Resources tab in Retool and click Add Resource → REST API.

In the configuration form:
- Name: 'Signal Bridge' or 'Signal - Alerts'
- Base URL: your bridge's HTTPS URL (e.g., https://signal-bridge.internal.yourcompany.com or the HTTP URL if using private networking with self-hosted Retool)

For authentication, configure HTTP Basic Auth with the credentials you set up on your nginx reverse proxy or the container's built-in auth. This prevents unauthorized access to the Signal sending endpoint.

If your bridge requires a specific API version path prefix (/v1/), you can include this in the Base URL (e.g., https://signal-bridge.internal.yourcompany.com/v1) so query paths only need to specify the endpoint name (e.g., /send).

For Retool Cloud accessing a private bridge, you will need to expose the bridge with HTTPS through a reverse proxy. For self-hosted Retool within the same private network, you can use the internal HTTP URL and IP address directly.

Store any authentication credentials in Retool configuration variables (Settings → Configuration Variables, marked as secret). Click Save Changes to finalize the resource.

Test the connection by creating a query with Method GET and URL /v1/health. The bridge should respond with a 200 status confirming the service is operational.

**Expected result:** A Signal Bridge Resource appears in your Retool Resources list. A test health check query returns a 200 response from the bridge, confirming Retool can communicate with the self-hosted Signal service.

### 4. Send Signal messages from Retool apps

The signal-cli-rest-api bridge provides a POST /v1/send endpoint for sending messages to Signal contacts or groups. The request body specifies the sender number (your registered phone number), the message text, and the recipient(s) — either individual phone numbers or Signal group IDs.

In a Retool app, create a query with Method POST and URL /v1/send (or the full path if your base URL doesn't include the /v1 prefix). Configure the JSON body as follows:

The message field is the only required content field. You can include dynamic data from Retool queries and component values using {{ }} expressions — for example, referencing the selected row in a Table to include an incident ID or alert value in the message text.

For team notifications, use Signal group IDs rather than individual phone numbers. To get a group ID, first create a Signal group through the bridge's groups API, then add recipients to the group. Group IDs are UUIDs returned by the bridge's group creation endpoint.

Add a Button component to the canvas and connect it to this query via an event handler. Always add a confirmation dialog to the button — Signal messages cannot be recalled once sent. In the confirmation message, show a preview of what will be sent: 'Send Signal alert to security team? Message: {{ messagePreview }}'.

In the On Success event handler, show a Retool notification confirming the message was sent and optionally log the alert to your database with timestamp, recipient, and message summary.

```
// POST body for signal-cli-rest-api /v1/send endpoint
// Sends a Signal message from Retool
{
  "message": "[RETOOL ALERT] {{ alertTypeSelect.value }}\n\nDetails: {{ alertDetailsInput.value }}\n\nTime: {{ new Date().toISOString() }}\n\nInitiated by: {{ current_user.email }}",
  "number": "+15551234567",
  "recipients": [
    "{{ recipientInput.value }}"
  ]
}
```

**Expected result:** Clicking the 'Send Signal Alert' button in the Retool app (after confirming the dialog) sends a Signal message to the configured recipient. The message appears in the Signal app on the recipient's device, encrypted end-to-end.

### 5. Build a Retool Workflow for automated Signal alerts

For automated Signal notifications triggered by data conditions rather than user actions, use Retool Workflows. Navigate to the Workflows section in the Retool home page sidebar and click New Workflow.

Click Add Trigger and select Schedule. For a compliance monitoring use case, set the schedule to every 15 minutes using a cron expression: */15 * * * *. For security incident monitoring, you might prefer every 5 minutes.

Add a Resource Query block connected to your PostgreSQL database. Write a SQL query that identifies the condition you want to monitor:

Add a Branch block after the database query with the condition {{ block1.data.length > 0 }}. This ensures the Signal message is only sent when the condition is actually met — not on every trigger run.

In the 'true' branch, add a Resource Query block connected to your Signal Bridge resource. Set Method to POST and path to /v1/send. Construct the message body dynamically using data from the database query block: reference the block's output using the block name (e.g., {{ block1.data[0].event_type }}).

Add a second Resource Query block in the 'true' branch to log the alert to your database — insert a record into an alerts_log table with the trigger condition, message content, timestamp, and recipients. This creates an audit trail of all automated alerts sent.

Click Publish Release to activate the Workflow. Monitor the Runs tab to verify it executes correctly on schedule.

```
-- SQL query for the database monitoring block in the Workflow
-- Detects high-sensitivity data access events in the last 15 minutes
SELECT
  user_id,
  username,
  event_type,
  table_name,
  record_count,
  accessed_at
FROM audit_log
WHERE
  data_sensitivity IN ('PHI', 'PII', 'CONFIDENTIAL')
  AND accessed_at > NOW() - INTERVAL '15 minutes'
  AND alerted = false
ORDER BY accessed_at DESC;
```

**Expected result:** The Workflow runs on the configured schedule, checks the database for alert conditions, and sends Signal messages only when conditions are met. All alerts are logged to the database. The Runs tab shows successful executions with per-block status.

## Best practices

- Use Signal integration only when end-to-end encryption is a genuine security requirement — for most operational alerts, Slack, Teams, or Twilio SMS provide adequate security with significantly simpler setup and maintenance.
- Deploy the signal-cli-rest-api bridge within a private VPC subnet when using self-hosted Retool — this eliminates the need for HTTPS exposure and reduces the attack surface of the Signal bridge.
- Protect the signal-cli-rest-api bridge with HTTP Basic Auth or API key authentication — an unauthenticated Signal bridge can be abused to send messages at scale from your registered number.
- Persist the signal-cli registration volume (the ./signal-cli-config directory) and back it up regularly — losing this data requires a full re-registration with a new verification SMS, causing downtime.
- Add confirmation dialogs to all buttons that trigger Signal messages in Retool apps — Signal does not support message recall, so accidental sends cannot be undone.
- Log all Signal alerts to your own database with message content, recipients, timestamp, and initiating user — Signal's end-to-end encryption means even Retool cannot retrieve sent message history after the fact.
- Use Signal group chats rather than individual numbers for team notifications — groups can be modified (members added/removed) without changing the sending logic in your Retool queries.

## Use cases

### Build a security incident notification system

Create a Retool security operations panel where analysts can trigger Signal alerts to the security response team when a potential incident is detected. The Signal message contains the incident ID, severity, affected systems, and a secure link back to the Retool incident dashboard. All message content stays end-to-end encrypted and never passes through a third-party notification service, satisfying security policies that prohibit sensitive alert content on corporate messaging platforms.

Prompt example:

```
Build a Retool security incident panel that queries the incidents table for open events with severity 'High' or 'Critical'. Show incidents in a Table with ID, type, affected_system, detected_at, and status columns. Add a 'Send Signal Alert' button that sends a formatted Signal message to the security-team group with the incident ID, severity, and a link to the Retool dashboard. Include a confirmation dialog before sending.
```

### Create compliance alerts for regulated data access events

Build a Retool Workflow that monitors a PostgreSQL audit log for high-sensitivity data access events — bulk PII exports, access to protected health information, or unusual query patterns. When a threshold is crossed, the Workflow sends a Signal message to the compliance officer's number with the event details. Because Signal encrypts messages end-to-end, the compliance notification itself does not expose PII in transit through any intermediary service.

Prompt example:

```
Create a Retool Workflow with a 15-minute schedule trigger that queries the audit_log PostgreSQL table for events where data_sensitivity = 'PHI' or 'PII' and accessed_at > NOW() - INTERVAL '15 minutes'. If any events are found, send a Signal message to the compliance team group listing the user, timestamp, record count, and data type accessed. Log the alert in a compliance_alerts table.
```

### Build an executive-only alert system for financial thresholds

Create a Retool Workflow that monitors key financial metrics — revenue drop below a threshold, unusual transaction volumes, payment processor failures — and sends encrypted Signal messages directly to executive phone numbers when thresholds are breached. Because the alerts go to personal Signal numbers rather than a shared channel, the information remains limited to designated recipients and is end-to-end encrypted throughout.

Prompt example:

```
Build a Retool Workflow that queries the financial_metrics table hourly. If revenue for the current hour is more than 40% below the same-hour average for the last 30 days, send a Signal message to the CFO's phone number with the current revenue figure, the expected range, and the percentage deviation. Include a link to the revenue dashboard and set the alert to not repeat for the same period within 4 hours.
```

## Troubleshooting

### signal-cli-rest-api container starts but sends return 'Failed to send message: Not connected'

Cause: The phone number is not registered with Signal's servers, or the registration data volume was lost or corrupted. This also occurs if the container was restarted without a persistent volume configuration.

Solution: Check the container logs with docker logs signal-cli-rest-api for specific error messages. If the registration data is missing, re-run the registration steps (Step 2 in this guide) — request a new verification SMS and re-register the number. Ensure the Docker volume mount in your docker-compose.yml points to a persistent directory that survives container restarts. Verify the registered number appears in GET /v1/accounts on the bridge.

### Retool Resource query to the bridge returns a connection timeout or 'ECONNREFUSED'

Cause: Retool's server-side proxy cannot reach the signal-cli-rest-api bridge. For Retool Cloud, the bridge must be HTTPS-accessible from the internet. For self-hosted Retool, the bridge must be reachable from the Retool server's network.

Solution: Test the bridge URL directly from your Retool server using curl or a browser. For Retool Cloud, ensure the bridge has a public HTTPS endpoint with a valid TLS certificate — self-signed certificates require configuring the NODE_EXTRA_CA_CERTS environment variable on your self-hosted Retool instance. For private deployments, verify the bridge's IP and port are accessible from the Retool server and not blocked by firewall rules.

### Signal messages are sent from Retool but arrive with an unknown contact identity (no name shown)

Cause: The profile name for the registered Signal number was not configured, or the recipient has not saved your dedicated number as a contact in their Signal app.

Solution: Configure the bridge's profile name via PUT /v1/profiles/+YOUR_NUMBER with a JSON body { "name": "Your Org Alerts" }. This sets the display name that appears in Signal even for unknown contacts. Advise recipients to save your dedicated alert number as a contact in their Signal app so messages appear with a recognizable name rather than the raw phone number.

### Bridge sends to individual numbers but fails with 'Group not found' for group messages

Cause: Group IDs in Signal's internal format (used by signal-cli) differ from user-visible group names. The group may not have been created through the bridge, or the group ID format is incorrect.

Solution: Create groups through the bridge's group management API rather than through the Signal app directly — groups created in the Signal app are visible to the bridge but their internal IDs must be fetched via GET /v1/groups/+YOUR_NUMBER. Use the returned groupId (a Base64-encoded string) in your send requests rather than the group name.

## Frequently asked questions

### Does Signal have an official REST API for business use?

No. Signal does not provide an official public API for third-party integrations. The only supported programmatic access is through the open-source signal-cli library, which this guide wraps in the signal-cli-rest-api Docker container. Signal's official position is that the encryption protocol and app are for personal communication. Some organizations use Signal Business or Signal for enterprise communication but these do not have formal API programs as of 2026.

### Is this Signal integration compliant with Signal's terms of service?

Signal's terms of service prohibit using the service to send spam or bulk automated messages. The integration described in this guide is intended for low-volume operational alerts (security incidents, compliance events) where the encrypted delivery is the primary value — not high-volume notification broadcasting. Using signal-cli for mass messaging or automated bulk outreach would violate Signal's terms. Review Signal's terms before deploying and keep message volume low and purposeful.

### Can Retool receive incoming Signal messages from the bridge?

The signal-cli-rest-api bridge can receive incoming Signal messages, but Retool cannot directly receive webhooks (incoming HTTP requests). To process incoming Signal messages in Retool, set up a Retool Workflow webhook endpoint and have a middleware service (a simple API on your infrastructure) receive messages from the bridge and forward them to the Retool Workflow webhook URL. This is significantly more complex than the sending use case and is only needed if you're building a two-way Signal communication dashboard.

### What phone number format does signal-cli-rest-api require?

All phone numbers in signal-cli-rest-api must be in E.164 international format: a plus sign followed by the country code and subscriber number, with no spaces, dashes, or parentheses. For example, US number 555-123-4567 becomes +15551234567, and UK number 07911 123456 becomes +447911123456. Using incorrect formatting causes registration and sending failures without clear error messages in some cases.

---

Source: https://www.rapidevelopers.com/retool-integrations/signal
© RapidDev — https://www.rapidevelopers.com/retool-integrations/signal
