Install on your ESP32
Flash MicroPython 1.29, connect the ESP32 to your Mac/PC over USB, and run this command. It downloads release files, asks for your agent name, API key, and Wi-Fi credentials, and deploys everything to the board:
# on your Mac/PC
curl -fsSL https://raw.githubusercontent.com/ctrlpi/esp32-gpio-api/main/install.sh | bashPre-compiled bytecode, zero extra dependencies
app.mpy is pre-compiled into bytecode for fast boot times and reduced RAM usage. boot.py connects to Wi-Fi at startup and launches the server automatically.
Wi-Fi credentials live in wifi.txt on the board (install.sh writes it from a prompt):
SSID = "YourNetwork" PASSWORD = "YourPassword"
What it does
- Outputs: write
0/1/"on"/"off"/"toggle", pulse for a duration with automatic revert, clamp with a per-pinmax, invert relay logic withreversed - Inputs: pull-up/down/none, name aliases, and
watchedpins that fire a webhook on every state change - Sensors: named readings from a MicroPython script in the agent's
scripts/folder, returned as JSON - Persistence: pin config and last output values survive restarts and reboots (
init: "last") - Identity: every agent reports its name, IP, platform, OS, and CPU temperature; unauthenticated
/hellomakes LAN discovery trivial - Logging: request log with configurable retention (
log_days0 to 7), readable over the API
The REST API
All routes require the Api-Key header except /hello:
| Method | Path | Description |
|---|---|---|
GET | /hello | Discovery & health check, returns the agent's name, no auth |
GET | /gpio/read | Read all configured pins |
GET | /gpio/read/{name_or_gpio} | Read one pin by GPIO number or name alias |
POST | /gpio/write/{name_or_gpio} | Write a value, supports "on"/"off"/"toggle" and timed duration pulses |
POST | /gpio/config/{name_or_gpio} | Configure a pin: type, name, init, pullup, max, reversed, watched |
GET | /gpio/watched | List watched pins and the active webhook URL |
GET | /gpio/scan | Scan all usable GPIO pins, includes physical level, platform, CPU temp |
POST | /sensor/config/{name} | Configure a named sensor: a script (.py) to run from the agent's scripts/ folder |
GET | /sensor/read | Read all sensors (or /sensor/read/{name} for one) as JSON |
GET | /config/read | Agent identity + full config |
POST | /config/update | Update config fields (auto-backup first) |
POST | /config/load | Replace the whole config ({} resets) |
POST | /restart | Restart the device - resets microcontroller into clean state |
POST | /upgrade | Upgrade in place - downloads latest release files and resets |
GET | /logs | Last 30 log lines as JSON (in-memory, cleared on reboot) |
Try it
# configure GPIO 18 as an output named "led" curl -X POST http://<esp32-ip>:8314/gpio/config/18 \ -H "Api-Key: your-secret-key" -H "Content-Type: application/json" \ -d '{"type": "output", "name": "led"}' # pulse it for 1.5 seconds, reverts automatically curl -X POST http://<esp32-ip>:8314/gpio/write/led \ -H "Api-Key: your-secret-key" -H "Content-Type: application/json" \ -d '{"value": 1, "duration": 1.5}'
Webhooks
Mark any pin watched and the agent POSTs its state to your configured
webhook URL on every change, that's how
homebridge-ctrlpi gets real-time input events. While setting up,
point webhook_url at ctrlPi's public test endpoint and
watch your events live while wiring.
In the family
Everything that drives a Pi or Pico agent drives an ESP32 agent unchanged: homebridge-ctrlpi, mcp-bridge, ctrlpi-cli, and ctrlpi-lab. Watch live webhooks at ctrlpi.com.
To test endpoints, watch webhook events and tail logs in the browser, open ctrlpi-lab, and to find and drive agents from a terminal, use ctrlpi-cli.
To get an agent onto a board over USB, use pico-bay. It can install MicroPython, manage the board's files and run code on a Pico and an ESP32.