signal-cli-rest-api

Signal Node for n8n using signal-cli-rest-api

Package Information

Released: this month
Downloads: 46 weekly / 364 monthly
Latest Version: 0.13.0

Documentation

n8n Signal Node

n8n Signal

Custom n8n node for Signal messenger integration

Send secure messages and automate Signal workflows with n8n


📋 Table of Contents

🚀 Features

  • Send Messages: Send text messages to individuals or groups
  • Send Media: Send images, files, and attachments
  • Reply to Messages: Reply to a specific message with a quote reference
  • Forward Messages: Forward a message, including its attachments, to another contact or group
  • Reactions: React to messages or remove reactions
  • Typing Indicators: Show/hide typing status
  • Read Receipts: Mark messages as read
  • Polls: Create, close, and vote on Signal polls
  • Search: Check if phone numbers are registered with Signal
  • Group Management: Create, update, and list Signal groups
  • Contact Management: List contacts for the account
  • Attachment Handling: List, download, and remove attachments
  • Message Reception: Trigger workflows on incoming messages via WebSocket
  • Secure Communication: Leverages Signal's end-to-end encryption
  • REST API Integration: Uses signal-cli-rest-api for reliable communication

🛠 Prerequisites

Before using this n8n Signal node, you need to set up the Signal CLI REST API service:

1. Signal CLI REST API Setup

Create a docker-compose.yml file with the following configuration:

version: '3'
services:
  signal-cli-rest-api:
    image: bbernhard/signal-cli-rest-api:latest
    container_name: signal-cli-rest-api
    restart: unless-stopped
    ports:
      - "8085:8080"
    volumes:
      - /mnt/your-pool/signal-data:/home/.local/share/signal-cli
    environment:
      - MODE=json-rpc  # Recommended for speed and group reception
      - AUTHENTICATION_API_TOKEN=your-secret-token  # Optional

2. Signal Account Registration

  1. Start the Docker container:

    docker-compose up -d
    
  2. Link with existing Signal app using QR code:

    http://localhost:8085/v1/qrcodelink?device_name=n8n-signal
    
  3. Or register a new number:

    curl -X POST 'http://localhost:8085/v1/register/+1234567890'
    

📦 Installation

Method 1: n8n Community Package Manager

  1. In your n8n instance, go to Settings → Community Nodes
  2. Click Install a community node
  3. Enter the package name: n8n-nodes-signal-cli-rest-api
  4. Click Install

Method 2: Manual Installation

npm install n8n-nodes-signal-cli-rest-api

Method 3: Development Setup

git clone https://github.com/zblaze/n8n-nodes-signal.git
cd n8n-nodes-signal
npm install
npm run build

⚙️ Configuration

Credentials Setup

In n8n, create new credentials for Signal API and configure:

Field Description Example
API URL URL of your signal-cli-rest-api instance http://localhost:8085
Phone Number Registered Signal phone number +1234567890
API Token Optional Bearer token for authentication your-secret-token

🔧 Operations

Messages

Operation Description
Send Message Send a text message to a contact or group, optionally with file attachments
Send Reaction React to a message with an emoji
Remove Reaction Remove a previously sent reaction
Start Typing Show typing indicator to a recipient
Stop Typing Stop showing typing indicator
Mark As Read Send a read receipt for a message
Reply Message Reply to a specific message with a quote reference
Forward Message Forward a message, including its attachments, to another contact or group

Send Message — parameters

Parameter Required Description
Recipient ✅ Phone number or group ID
Message Text content (optional if sending attachments)
Binary Fields One or more binary fields containing files to attach
Timeout Request timeout in seconds (default: 60)

Send Reaction — parameters

Parameter Required Description
Recipient ✅ Phone number or group ID
Emoji ✅ Reaction emoji (predefined list or custom)
Target Author ✅ Phone number or UUID of the original message author
Target Message Timestamp ✅ Timestamp of the message to react to (ms)

Reply Message — parameters

Parameter Required Description
Recipient ✅ Phone number or group ID to send the reply to
Message Reply text (optional if sending attachments)
Target Author ✅ Phone number or UUID of the original message's author
Target Message Timestamp ✅ Timestamp of the message being replied to (ms)
Quoted Message Text Text snippet of the original message shown in the quote preview (optional but recommended)
Binary Fields One or more binary fields containing files to attach
Timeout Request timeout in seconds (default: 60)

There's no dedicated "reply" endpoint — this sends signal-cli-rest-api's quote_timestamp / quote_author / quote_message fields alongside a regular send. Bind Target Author / Target Message Timestamp to the message you're replying to, e.g. from a Signal Trigger item: {{ $json.sourceUuid }} / {{ $json.timestamp }}. Target Author accepts a UUID (recommended — many Signal users don't expose a phone number at all) or a phone number.

Forward Message — parameters

Parameter Required Description
Recipient ✅ Phone number or group ID to forward the message to
Message Text content to forward (e.g. the original messageText from the trigger)
Source Attachment IDs Comma-separated attachment IDs from the original message (from the trigger's attachments field) — fetched from the server and re-sent automatically
Timeout Request timeout in seconds (default: 60)

There's no native "forward" call either — bind Message and Source Attachment IDs by expression to the Signal Trigger's output, e.g. {{ $json.messageText }} and {{ $json.attachments.map(a => a.id).join(',') }}. Works with zero, one, or many attachments in the same call, no IF node needed. It won't carry Signal's built-in "Forwarded" badge, since that's not exposed by the API. Passing the mapped array directly (without .join(',')) also works — see note below.


Attachments

Operation Description
List Attachments List all stored attachments for the account
Download Attachment Download an attachment as a binary file
Remove Attachment Delete an attachment from the server

Contacts

Operation Description
Get Contacts Retrieve the full contact list for the account

Groups

Operation Description
Get Groups Retrieve all groups for the account (may be slow — use timeout 300s)
Create Group Create a new Signal group with a name and initial members
Update Group Update a group's name or member list

Create / Update Group — parameters

Parameter Required Description
Group ID ✅ (update only) ID of the group to update
Group Name New name for the group
Group Members Comma-separated phone numbers

Polls

Signal polls let you send a question with multiple-choice answers to a contact or group.

Operation Description
Create Poll Send a new poll to a contact or group
Close Poll Close an existing poll so no more votes can be submitted
Vote on Poll Submit a vote on a poll

Create Poll — parameters

Parameter Required Description
Recipient ✅ Phone number, username, or group ID
Question ✅ The poll question
Answers ✅ One answer per line (minimum 2)
Allow Multiple Selections Whether voters can select more than one answer (default: false)

Response includes a timestamp field — save it, you'll need it to close the poll or submit votes.

Close Poll — parameters

Parameter Required Description
Recipient ✅ Same recipient the poll was sent to
Poll Timestamp ✅ Timestamp returned when the poll was created

Vote on Poll — parameters

Parameter Required Description
Recipient ✅ Same recipient the poll was sent to
Poll Timestamp ✅ Timestamp returned when the poll was created
Poll Author ✅ Phone number or UUID of the poll creator
Selected Answer Indexes ✅ Comma-separated 0-based indexes (e.g. 0,2)

Search

Operation Description
Check Registration Check if one or more phone numbers are registered with Signal

Check Registration — parameters

Parameter Required Description
Phone Numbers ✅ Comma-separated list of numbers to check

Response example:

{
  "results": [
    { "number": "+1234567890", "registered": true },
    { "number": "+0987654321", "registered": false }
  ]
}

Signal Trigger

The Signal Trigger node starts a workflow when a new message arrives via WebSocket.

Parameter Description
Reconnect Delay Seconds to wait before reconnecting on disconnect
Ignore Messages Skip messages with text content
Ignore Attachments Skip messages with attachments
Ignore Reactions Skip messages with reactions

Output fields:

Field Description
messageText Text content of the message
attachments List of received attachments (Signal's text/x-signal-plain long-text pseudo-attachment is excluded — its content is merged into messageText instead, see note below)
reactions Reaction data if present
sourceName Display name of the sender
sourceUuid UUID of the sender
groupInternalId Group ID (if message was in a group)
groupName Group name (if message was in a group)
timestamp Message timestamp (use for reactions, read receipts, polls)
messageType incoming or outgoing
envelope Full raw envelope from Signal

Tip: The timestamp from the trigger output is what you pass as Target Message Timestamp, Poll Timestamp, etc. in subsequent nodes. For Forward Message, the id of each entry in attachments is what you pass as Source Attachment IDs.

Note on list fields (Source Attachment IDs, Group Members, Selected Answer Indexes, Phone Numbers): when a field's expression is entirely {{ ... }} with nothing else around it, n8n resolves it to its real type instead of stringifying it — so {{ $json.attachments.map(a => a.id) }} arrives as an actual array, not a joined string. Both a plain array expression and an explicit .join(',') are accepted here.

Note on timestamps: signal-cli-rest-api is inconsistent here — /v2/send's response returns timestamp as a JSON string, while Target Message Timestamp fields (reactions, read receipts, Reply Message) need to send it as a JSON number. This node accepts either shape and converts, so piping a Send Message response's timestamp straight into a later node's Target Message Timestamp works without an intermediate conversion step.

Note on long messages: when a message body exceeds ~2KB, Signal truncates the regular text field and ships the full original text as a text/x-signal-plain pseudo-attachment instead (this is standard Signal protocol behavior, not a bug on either end). This node detects that attachment, downloads its content, and uses it as messageText — so you always get the untruncated text — while excluding the entry from attachments (it's not a real file). If the download fails, messageText falls back to the truncated body and a warning is logged.


🐞 Troubleshooting

"Specified account does not exist"

Verify your registered account via:

curl http://<host>:<port>/v1/accounts

Compare the returned number character-by-character against the Phone Number in your n8n credentials — a typo is the most common cause.

Get Groups is slow or times out

Set Timeout to 300 seconds for the Get Groups operation.

Attachments not downloading

Check that the attachment ID is correct (use the value from the trigger's attachments field).


🤝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

💖 Support the Developer

Ko-Fi
Coinbase Commerce


📄 License

MIT License — see LICENSE for details.

🔗 Related Links


Made with ❤️ for the n8n community

Discussion