This ESP32 API guide describes how to implement an ESP32 Rest API server using PlatformIO. As you may already know, API stands for Application Programming Interface. The aim of this tutorial is to build an ESP32 API Web server so that the ESP32 exposes a set of Rest API. We can use these Rest APIs to interact with ESP32. We will focus our attention on developing JSON Rest APIs that use the GET and POST method. Through an ESP32 API server, we will implement four different Rest JSON APIs.
To apply this ESP32 API guide to a real use case, we will connect the ESP32 to a BME280 sensor to read the temperature, humidity, and pressure. Therefore, the ESP32 API Server will expose three different JSON APIs:
- to read the temperature
- to read the pressure
- to read the humidity
Moreover, we will implement another JSON API that supports POST method to send data to the ESP32.
What you will learn…
- How to develop ESP32 Rest APIs:
- How to implement Rest JSON API that supports GET method
- How to implement a Rest JSON API that supports POST method
- How to implement an ESP32 API Web server to handle HTTP connections
To build these projects you will need the following libraries:
adafruit/Adafruit BMP280 Library @ ^2.1.0
adafruit/Adafruit Unified Sensor @ ^1.1.4
bblanchon/ArduinoJson @ ^6.17.2
adafruit/Adafruit NeoPixel @ ^1.7.0
How to develop an ESP32 API server
The first step is developing an ESP32 API Web server that handles the incoming client connections. As you should know already, a Rest API uses the HTTP protocol so it is necessary to create a Web server. Create a new project using your favorite IDE, I’m using PlatformIO, and use the code shown below:
#include <WiFi.h>
#include <WebServer.h>
const char *SSID = "your_wifi_ssid";
const char *PWD = "your_wifi_pwd";
// Web server running on port 80
WebServer server(80);
void connectToWiFi() {
Serial.print("Connecting to ");
Serial.println(SSID);
WiFi.begin(SSID, PWD);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
// we can even make the ESP32 to sleep
}
Serial.print("Connected. IP: ");
Serial.println(WiFi.localIP());
}
Code language: PHP (php)
In line 6, the code defines the Web server listening on port 80. You can change this port if you like.
We have our Web server running on the ESP32. To make it an ESP32 API server, we have to add resources to handle. An interested application about using API in IoT is using ESP32-CAM with Machine Learning to recognize images.
How to add Rest API resources to the ESP32
Now, we have to add API resources to the ESP32. Our ESP32 API server must support:
- /temperature – GET method – that returns the temperature
- /pressure – GET method – that returns the pressure
- /humidity – GET method – that returns the humidity
- /env – GET – that returns all the previous information toghether
Let us add an API routing so that the Web server will dispatch the request to th right API handler:
// setup API resources
void setup_routing() {
server.on("/temperature", getTemperature);
server.on("/pressure", getPressure);
server.on("/humidity", getHumidity);
server.on("/env", getEnv);
// start server
server.begin();
}
Code language: JavaScript (javascript)
The code assign to each resources the corresponding hanlder. Finally it starts the ESP32 API server.
How to implement the ESP32 Rest API
It is time to implement the Rest API. The code is simple:
void getTemperature() {
Serial.println("Get temperature");
create_json("temperature", temperature, "°C");
server.send(200, "application/json", buffer);
}
void getHumidity() {
Serial.println("Get humidity");
create_json("humidity", humidity, "%");
server.send(200, "application/json", buffer);
}
void getPressure() {
Serial.println("Get pressure");
create_json("pressure", pressure, "mBar");
server.send(200, "application/json", buffer);
}
void getEnv() {
Serial.println("Get env");
jsonDocument.clear(); // Clear json buffer
add_json_object("temperature", temperature, "°C");
add_json_object("humidity", humidity, "%");
add_json_object("pressure", pressure, "mBar");
serializeJson(jsonDocument, buffer);
server.send(200, "application/json", buffer);
}
Code language: JavaScript (javascript)
Our ESP32 Rest API returns a JSON payload. To do it, the code uses the ArduinoJSON library. Finally the server return the payload to the client.
Return the JSON Payload
In this step, we will create the JSON payload that holds the information the client requested using the ESP32 Rest API:
#include <ArduinoJson.h>
// JSON data buffer
StaticJsonDocument<250> jsonDocument;
char buffer[250];
void create_json(char *tag, float value, char *unit) {
jsonDocument.clear();
jsonDocument["type"] = tag;
jsonDocument["value"] = value;
jsonDocument["unit"] = unit;
serializeJson(jsonDocument, buffer);
}
void add_json_object(char *tag, float value, char *unit) {
JsonObject obj = jsonDocument.createNestedObject();
obj["type"] = tag;
obj["value"] = value;
obj["unit"] = unit;
}
Code language: PHP (php)
How to implement ESP32 Rest API with POST method
In the previous paragraph, we have described how to implement Rest JSON APIs that support HTTP GET method. This kind of API is used to get (or read) data. It is a read-only API.
Now we conver how to implement a Rest JSON API that uses the POST method. In this case, the client has to send a payload that is the information the client wants to send to the ESP32. Moreover, we suppose the payload is in JSON format.
Let us add the following resources to the ESP32 API server in the setup_routing()
method:
server.on("/led", HTTP_POST, handlePost);
Code language: JavaScript (javascript)
In this case we add another resource named led that explicity supports HTTP Post method. We use this Rest JSON API to control a led strip color.
Handle POST payload
To handle the POST payload that the ESP32 API server receives when the client invokes this Rest JSON API, it is necessary to add the following code:
void handlePost() {
if (server.hasArg("plain") == false) {
//handle error here
}
String body = server.arg("plain");
deserializeJson(jsonDocument, body);
// Get RGB components
int red = jsonDocument["red"];
int green = jsonDocument["green"];
int blue = jsonDocument["blue"];
// Respond to the client
server.send(200, "application/json", "{}");
}
Code language: JavaScript (javascript)
Notice that, we deserialize the JSON payload and the get the three color components. Finally, we send back a response to the client using an empty payload.
It is possible to implement not only an API server but an API client too. If you want to know more, you can read how to develop an ESP8266 JSON client. The API plays an important role in IoT and using it, it is possible to integrate different devices easily. For example, you can learn how to develop Arduino Rest API.
Recommended:
How to invoke HTTPS Rest JSON API using ESP8266: ClimaCell API example
#API and IoT the perfect convergence: Arduino Rest API
How to implement a WebSocket Server using ESP32
ESP32 Rest API Server: Full source code
This is the full source code:
#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include <ArduinoJson.h>
#include <FreeRTOS.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_NeoPixel.h>
const char *SSID = "your_wifi_ssid";
const char *PWD = "your_wifi_pwd";
#define NUM_OF_LEDS 8
#define PIN 4
// Web server running on port 80
WebServer server(80);
// Sensor
Adafruit_BME280 bme;
// Neopixel LEDs strip
Adafruit_NeoPixel pixels(NUM_OF_LEDS, PIN, NEO_GRB + NEO_KHZ800);
// JSON data buffer
StaticJsonDocument<250> jsonDocument;
char buffer[250];
// env variable
float temperature;
float humidity;
float pressure;
void connectToWiFi() {
Serial.print("Connecting to ");
Serial.println(SSID);
WiFi.begin(SSID, PWD);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
// we can even make the ESP32 to sleep
}
Serial.print("Connected. IP: ");
Serial.println(WiFi.localIP());
}
void setup_routing() {
server.on("/temperature", getTemperature);
server.on("/pressure", getPressure);
server.on("/humidity", getHumidity);
server.on("/env", getEnv);
server.on("/led", HTTP_POST, handlePost);
// start server
server.begin();
}
void create_json(char *tag, float value, char *unit) {
jsonDocument.clear();
jsonDocument["type"] = tag;
jsonDocument["value"] = value;
jsonDocument["unit"] = unit;
serializeJson(jsonDocument, buffer);
}
void add_json_object(char *tag, float value, char *unit) {
JsonObject obj = jsonDocument.createNestedObject();
obj["type"] = tag;
obj["value"] = value;
obj["unit"] = unit;
}
void read_sensor_data(void * parameter) {
for (;;) {
temperature = bme.readTemperature();
humidity = bme.readHumidity();
pressure = bme.readPressure() / 100;
Serial.println("Read sensor data");
// delay the task
vTaskDelay(60000 / portTICK_PERIOD_MS);
}
}
void getTemperature() {
Serial.println("Get temperature");
create_json("temperature", temperature, "°C");
server.send(200, "application/json", buffer);
}
void getHumidity() {
Serial.println("Get humidity");
create_json("humidity", humidity, "%");
server.send(200, "application/json", buffer);
}
void getPressure() {
Serial.println("Get pressure");
create_json("pressure", pressure, "mBar");
server.send(200, "application/json", buffer);
}
void getEnv() {
Serial.println("Get env");
jsonDocument.clear();
add_json_object("temperature", temperature, "°C");
add_json_object("humidity", humidity, "%");
add_json_object("pressure", pressure, "mBar");
serializeJson(jsonDocument, buffer);
server.send(200, "application/json", buffer);
}
void handlePost() {
if (server.hasArg("plain") == false) {
//handle error here
}
String body = server.arg("plain");
deserializeJson(jsonDocument, body);
// Get RGB components
int red = jsonDocument["red"];
int green = jsonDocument["green"];
int blue = jsonDocument["blue"];
Serial.print("Red: ");
Serial.print(red);
pixels.fill(pixels.Color(red, green, blue));
pixels.show();
// Respond to the client
server.send(200, "application/json", "{}");
}
void setup_task() {
xTaskCreate(
read_sensor_data,
"Read sensor data",
1000,
NULL,
1,
NULL
);
}
void setup() {
Serial.begin(9600);
// Sensor setup
if (!bme.begin(0x76)) {
Serial.println("Problem connecting to BME280");
}
connectToWiFi();
setup_task();
setup_routing();
// Initialize Neopixel
pixels.begin();
}
void loop() {
server.handleClient();
}
Code language: PHP (php)
A few things to notice:
- The ESP32 connects to the BME280 to read temperature, pressure and humidity. The ESP32 retrieves this information using a specific task that runs very minute
- The ESP32 connects to Neopixel RGB led strip that is controlled using the ESP32 Rest API (POST method)
Before using BME280 and Nexopixels, you have to install the libraries if you didn’t do it already. If you use PlatformIO you can look for the libraries using the Library Manager.
If you do not have these components you can use other components to or you can just experiment how to work with ESP32 Rest API.
Moreover, there are other ways to interact with ESP32. For example, it is possible to use MQTT protocol. If you want to know more you can read how to develop an ESP32 MQTT client to publish BME280 sensor readings.
ESP32 Schematic
The ESP32 schematic is shown below:

How to test the ESP32 JSON Rest API
In this last step, we will test the ESP32 API server developed in the previous paragraph. There are several ways to test it, we will use Postman. You can download it freely.
Run the code on your ESP32 and open Postman.
To test the temperature API resource, get the ESP32 IP and then write:
http://192.168.1.169/temperature
Code language: JavaScript (javascript)
Change the IP according your ESP32:

In the same way you can test other JSON API resources:


Finally:

Testing the Rest JSON API with Post
In this last step, we test the Rest JSON API using POST HTTO method. In this case, we will send data to the ESP32:

Notice that we have used the POST method to invoke the Rest API on ESP32. If you have connected the led strips you will notice that the LEDs will change colors.
If you don’t want to use API and you have at least two ESP devices you can use ESP-Now protocol. You can learn more, reading my tutorial about how to use ESP-Now with ESP32 or ESP8266.
Wrapping up
At the end of this post, you learned how to implement an ESP32 API server that exposes a set of ESP32 Rest API. We can use these APIs to interact with the ESP32 or to exchange data. This is very helpful because once you have implemented your APIs then you can integrate the ESP32 with external systems such as mobile apps or other platforms. You can build for example an home automation system.
Hi there!
Thanks for your work, that code is perfect!
But can you explain which libraries are you using in that project?
I’ve updated the post with the library used. Thx
Hello, I’m unable to locate the WebServer.h library. Can you share it or point to where I can get it? Thanks
You can look here https://github.com/espressif/arduino-esp32/blob/master/libraries/WebServer/src/WebServer.h but it sounds strange to me you can’t find it. Check your installation before!
Nice tutorial. I’m designing a device that uses an ESP8266 or ESP32 connected to an SR-HC04 to read tank volume data and write it to Supabase (supabase.io) via Rest APIs. At the same time there will be a web app to read and plot the tank volume data. So I both read and write to Supabase. They have good documentation on their APIs.
I’ve glanced through your ESP8266 Rest API and the ESP32 Rest API tutorials but I’m confused between the client and servers terminology. Both seem to be able to do HTTP POST and GET.
What do I need to implement for the above use case?