January 14, 2026 Hunter McGuire

Send ESP32 sensor data to Slack in 5 minutes

From bare ESP32 to validated data in Slack. No broker setup, no Lambda functions, no glue code.

Most IoT tutorials stop at "your sensor is sending data." The hard part (validating it, storing it, and doing something when a reading is abnormal) is left as an exercise for the reader. This guide covers the full path.

What you'll build

Prerequisites

Step 1: Create an entity

In the Tendrl dashboard, go to Entities → Add Entity. Name it something like esp32-living-room. Copy the API key it shows you (it's shown once); the next step writes it to the board.

Step 2: Provision the board from the browser

Open the entity's Device tab in Chrome or Edge, plug the ESP32 into USB and click Connect. The browser talks to the board over WebSerial: it detects the chip, MicroPython version and free memory, and offers a Provision form. Paste the entity's API key, enter your Wi-Fi, keep the recommended install tier, click Start provisioning. That writes the SDK and the device config to the board over USB (the key never passes through our servers) and reboots it; it shows up online in Contact a few seconds later. The walkthrough has screenshots.

Prefer a terminal? The same install is one line at the MicroPython REPL, import mip; mip.install("https://app.tendrl.com/api/public/sdk/v1/latest/mpy/package.json"), plus a config.json with your API key and Wi-Fi. The browser just does both for you.

Step 3: Write the sensor script

Upload this as main.py (the Device tab's Files view does it from the same browser page). It reads the DHT22 every 30 seconds and publishes to Tendrl. The SDK handles Wi-Fi connection, TLS, batching, and offline queueing automatically.

main.py (ESP32)
import time
from machine import Pin
from dht import DHT22
from tendrl import Client

sensor = DHT22(Pin(4))
client = Client(mode="sync", offline_storage=True)
client.start()

while True:
    sensor.measure()
    client.publish(
        data={
            "temperature": sensor.temperature(),
            "humidity": sensor.humidity()
        },
        tags=["sensors", "dht22"]
    )
    time.sleep(30)

Power on the ESP32. Within a few seconds you should see messages arriving in the Tendrl dashboard under your entity.

Step 4: Add validation rules

Go to Services → Create Service. Add two validation rules:

Attach the service to your entity. Now every incoming message is validated before it's stored. A reading of temperature: 999 from a glitchy sensor gets rejected with a field-level error instead of silently corrupting your data.

Step 5: Build a Slack alert workflow

In Strand, create a new workflow. The flow is three nodes:

  1. Trigger: set to fire on incoming Contact messages with the sensors tag
  2. If/Else node with the condition {{ payload.temperature > 35 }}
  3. Slack connector: on the "true" branch, sends a message to your channel

For the Slack message, use a Jinja2 template:

Slack message template
High temperature alert: {{  payload.temperature  }}°C
Humidity: {{  payload.humidity  }}%
Entity: {{  meta.entity_name  }}

That's it. Your ESP32 sends data → Contact validates it → Strand checks the threshold → Slack gets the alert. No broker, no Lambda, no webhook handler.

What's next