Skip to content
Automation and AI

n8n SMS: how to send and receive text messages in a workflow from your own phone

Send SMS from n8n with the HTTP Request node and receive replies with a webhook. Includes paste-ready JSON, Google Sheets, Slack and AI reply recipes.

smsportal teamPublished: 8 min read

n8n SMS automation comes down to one HTTP request. smsportal has no dedicated n8n node, and you do not need one: send with the HTTP Request node, receive with the Webhook node. Messages go out from your own number, so customers can reply, and your workflow can react to the reply. Below are the exact node settings, paste-ready JSON and three recipes.

What do you need to send SMS from n8n?

You need an n8n instance (cloud or self-hosted), a smsportal account with an Android phone connected, and an API key. The phone is a one-time setup with a QR code, covered in the SMS API guide.

smsportal dashboard: devices and API keys
smsportal dashboard: devices and API keys

Tip: save the key as a Header Auth credential (header name x-api-key). That keeps it out of the exported workflow JSON.

How do you configure the HTTP Request node to send an SMS?

Set the method to POST, the URL to https://smsportal.app/api/v1/gateway/send-sms, add an x-api-key header and send a JSON body with recipients and message. The header is x-api-key, not Authorization. Using Authorization is the most common cause of a 401.

n8n fieldValue
MethodPOST
URLhttps://smsportal.app/api/v1/gateway/send-sms
AuthenticationGeneric Credential Type → Header Auth (x-api-key)
Send Bodyon
Body Content TypeJSON
Specify BodyUsing JSON

Use n8n expressions to pull the number and text from the previous node:

json
{
  "recipients": ["{{ $json.phone }}"],
  "message": "Hi {{ $json.name }}, your appointment is tomorrow at {{ $json.time }}."
}

With several phones, add "deviceId". For dual-SIM phones, add "simSubscriptionId". To send later, add "scheduledAt" with an ISO 8601 time in the future.

Paste-ready HTTP Request node (JSON)

Copy the JSON below and paste it onto an empty n8n canvas with Ctrl+V (Cmd+V on Mac). It creates an HTTP Request node with the header and JSON body. Replace YOUR_API_KEY, or swap the header for a Header Auth credential.

json
{
  "nodes": [
    {
      "parameters": {
        "method": "POST",
        "url": "https://smsportal.app/api/v1/gateway/send-sms",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            { "name": "x-api-key", "value": "YOUR_API_KEY" }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"recipients\": [\"{{ $json.phone }}\"],\n  \"message\": \"{{ $json.message }}\"\n}",
        "options": {}
      },
      "name": "Send SMS (smsportal)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [460, 300]
    }
  ],
  "connections": {}
}

The node expects the previous node to supply phone and message. Use international format, for example +14155550123.

Recipe 1: a new Google Sheets row sends an SMS

The Google Sheets Trigger with the Row added event starts the workflow when a row appears, and HTTP Request texts the number in that row. The trigger polls the sheet, so delivery follows its polling interval rather than being instant.

  1. Google Sheets Trigger → event Row added, pick your sheet. Columns such as phone, name, message.
  2. HTTP Request → settings from the table above, body using {{ $json.phone }} and {{ $json.message }}.
  3. (optional) Google Sheets → Update row: write the API response into a status column.

This suits simple notifications for a small business: a form writes a row, the customer gets a confirmation. For one message to hundreds of people, see bulk SMS from a CSV file.

Recipe 2: a customer reply goes to Slack or Telegram

The customer replies to your number, smsportal posts a MESSAGE_RECEIVED event to your Webhook node, and n8n forwards it to a chat app. Your team sees replies without opening the dashboard.

  1. Webhook → method POST, path such as incoming-sms. Copy the Production URL.
  2. In the smsportal dashboard open Webhooks, add the URL and tick MESSAGE_RECEIVED.
  3. Slack (Send a message) or Telegram (Send Message) with the text SMS from {{ $json.body.sender }}: {{ $json.body.message }}.

The Webhook node puts the request data under body, so expressions use $json.body.sender and $json.body.message. Each delivery also carries an idempotencyKey and an X-Signature header (HMAC-SHA256 of the body). Verification details are in the guide to receiving SMS with a webhook.

Note: register the production URL (without webhook-test) and activate the workflow. The test URL only works while the editor is listening.

Recipe 3: an AI step drafts the reply

After the Webhook node, add an AI node such as AI Agent or Basic LLM Chain with a chat model to draft a reply from the incoming text, then send it with the same HTTP Request node. Start by routing drafts to a human for approval.

  1. Webhook (MESSAGE_RECEIVED) provides sender and message.
  2. AI Agent / Basic LLM Chain, prompt: "Reply politely in under 160 characters, plain ASCII. Customer message: {{ $json.body.message }}".
  3. HTTP Request: recipients = {{ $('Webhook').item.json.body.sender }}, message = the model output.

For a setup where the model itself reads and sends texts, see SMS for AI agents through MCP. A hybrid also works well in n8n: the AI proposes, you approve in Slack, then the text goes out.

Activity list in the Android app with sent and received messages

How long can an SMS from n8n be?

A GSM-7 message holds 160 characters per segment. A single character outside the GSM-7 alphabet, such as an emoji or a Polish "ł", switches the whole message to UCS-2 and drops the limit to 70 per segment. Longer messages are joined from segments of 153 (GSM-7) or 67 (UCS-2) characters.

TextEncodingOne-segment limit
Hi Anna, see you tomorrow at 10:00.GSM-7160 characters
Hi Anna, see you tomorrow at 10:00 😊UCS-270 characters

The compose screen in the Android app shows a live counter for characters and segments.

How do you track status and failures?

The HTTP Request node tells you the message was accepted, not delivered. "Sent" means the phone handed the SMS to the carrier; "delivered" comes from the carrier's delivery report. To react to failures, build a second workflow with a Webhook on MESSAGE_FAILED.

  • MESSAGE_SENT: the phone sent the message,
  • MESSAGE_DELIVERED: the carrier confirmed delivery,
  • MESSAGE_FAILED: includes errorCode and errorMessage, handy for a Slack alert.

Enable Retry On Fail on the HTTP Request node so a brief network error does not drop a message. Remember that an offline phone holds queued messages for up to 72 hours, then they expire.

How do you test the workflow before going live?

Run the workflow against your own number before real customers are involved. Execute the HTTP Request node manually, check the response in n8n and the message status in the dashboard, then activate the trigger and switch to production data.

  1. Hard-code your own number in international format (+14155550123) and a short ASCII text.
  2. Click Execute step. The API response should be a 2xx.
  3. Watch the status move from queued to sent to delivered in the dashboard's Messages tab.
  4. Reply from a second phone while the Webhook node is on Listen for test event. The event should appear in the editor.
  5. Only then activate the workflow and paste the production URL into the dashboard.

Tip: while testing, put an IF node in front of the HTTP Request that only lets your own number through. A bad spreadsheet row then cannot text customers.

Troubleshooting: why is my n8n SMS not working?

Most failures come from five causes: the wrong header, a number without a country code, an offline phone, an unreachable webhook URL, or non-GSM characters. Here are the symptoms and fixes.

SymptomCauseFix
401 in the HTTP Request nodeAuthorization header instead of x-api-key, or a wrong keySend x-api-key with the key from the dashboard. With Header Auth, check the header name is exact
400, or the text never arrivesNumber without a country code (e.g. 4155550123)Use E.164 format with a leading + and country code. Add the prefix in an n8n expression if the source lacks it
API says OK, but the message stays queuedThe phone is offline or battery optimization pauses the appCheck signal, internet and the device health screen. Queued messages wait up to 72 hours, then expire
Webhook never firesThe URL is not a public HTTPS address, or you registered the test URLRegister the Production URL and activate the workflow. A self-hosted n8n on localhost is not reachable from the internet: use a tunnel or set the public address in the WEBHOOK_URL variable
One text counts as several segmentsAn emoji or accented letter switched the encoding to UCS-2Remove those characters or keep the text under 70. The compose screen shows the segment count

When events seem to be missing, open Executions in n8n. If a webhook call is listed there, the problem is in your nodes; if nothing is listed, the problem is the URL.

Limits: what not to do with n8n and a phone

An own-number phone gateway fits transactional messages, two-way conversations and alerts. The phone sends with a pause between messages (5 seconds by default), and carriers may block bulk sending from consumer SIMs, so do not use it for blasts of thousands per hour. For marketing volume pick a wholesale provider; see what an Android SMS gateway is and when not to use one.

Next step

Create a free smsportal account, connect a phone, paste the JSON above into n8n and text your own number. Request fields are in the API docs, and plans are on the pricing page.

Frequently asked questions

Is there a native smsportal node in n8n?

No. There is no native smsportal node, so you use two generic nodes: HTTP Request to send and Webhook to receive. Setup takes a few minutes and the same pattern works in every workflow.

How do I authenticate the n8n HTTP Request node?

Send an x-api-key header with the API key from your smsportal dashboard. Store it as a Header Auth credential so the key is not embedded in the workflow JSON when you export or share it.

How do I receive an SMS reply in n8n?

Create a workflow that starts with a Webhook node set to POST, copy its Production URL, and add it in the smsportal dashboard under Webhooks with the MESSAGE_RECEIVED event. The reply text and phone number arrive as message and sender.

Why does my webhook work in test mode but not after activation?

n8n uses two URLs: a test URL that is live only while the editor is listening, and a production URL that is live once the workflow is active. Register the production URL in smsportal and make sure the workflow is switched on.

Can n8n send thousands of texts at once?

n8n can fire the requests quickly, but the phone sends SMS with a pause between messages (5 seconds by default, about 720 per hour per phone). Spread large batches over time or add more devices.

Send your first SMS today

Create a free account, connect your phone and see how customers respond to messages from your number.