An ESP32 can act as a REST API client to read or send information in JSON format.
The example is oriented to ESP32. In many cases it can also be adapted to ESP8266 by changing libraries and a few pin details.
So far we have seen several ways to use ESP32 as a server, but it is also very common for the device to act as an HTTP client and consume services exposed by other machines.
To communicate two devices through HTTP, the server usually exposes an API through endpoints. Currently, the most common practice is to use a REST API and for the information exchange to be done using JSON.
In ESP32 projects it is very useful to interact with a REST API: read data, send measurements, query configurations, or trigger actions in another system.
Imagine, for example, that you have a Raspberry Pi that exposes an API where we can read or save sensor values. Or that we act with an IoT server to interact with the different servers.
For this post, we will use our usual example REST API that we saw in this post, which runs on NodeJs. We will also use Json files, so we recommend you read the post about Json in Arduino.
With all that, we have the components for our example of ESP32 as a REST API client. How complicated is it? Do not worry, not too much if we are organized. So let us get to work.
First, our main loop. It is similar to the example as an HTTP client, but we have added the reference to ‘ArduinoJson.h’ and to a file ‘API.hpp’ that will contain the functions to call to interact with the REST API.
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "config.h" // Replace with your network data
#include "API.hpp"
#include "ESP32_Utils.hpp"
void setup()
{
Serial.begin(115200);
ConnectWiFi_STA();
GetAll();
GetItem(1);
GetQuery("ABC");
Create("New item");
ReplaceById(2, "New item");
UpdateById(2, "New item");
DeleteById(5);
}
void loop()
{
}
On the other hand, we have the ‘API.hpp’ file that contains the functions that interact with the REST API. Here we have one function for each endpoint exposed by our example REST API, and they illustrate the usual requests for Get, Replace, Update and Delete, each with its methods and with the necessary parameters, either in the URL or in the request body encoded as Json.
On the other hand, we have the ‘processResponse(…)’ function that is responsible for collecting the server’s responses and performing the appropriate actions with them. In this case, we simply display them via serial port. In a real project, we would interpret the received data (probably another Json file) and execute the appropriate actions.
String ApiHost = "http://192.168.1.1:8080";
void processResponse(int httpCode, HTTPClient& http)
{
if (httpCode > 0) {
Serial.printf("Response code: %d\t", httpCode);
if (httpCode == HTTP_CODE_OK) {
String payload = http.getString();
Serial.println(payload);
}
}
else {
Serial.printf("Request failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
void GetAll()
{
HTTPClient http;
http.begin(ApiHost + "/item");
int httpCode = http.GET();
processResponse(httpCode, http);
}
void GetItem(int id)
{
HTTPClient http;
http.begin(ApiHost + "/item/" + id);
int httpCode = http.GET();
processResponse(httpCode, http);
}
void GetQuery(String filter)
{
HTTPClient http;
http.begin(ApiHost + "/item?filter=" + filter);
int httpCode = http.GET();
processResponse(httpCode, http);
}
void Create(String newData)
{
HTTPClient http;
http.begin(ApiHost + "/item");
http.addHeader("Content-Type", "application/json");
String message = "";
StaticJsonDocument<300> jsonDoc;
jsonDoc["data"] = newData;
serializeJson(jsonDoc, message);
int httpCode = http.POST(message);
processResponse(httpCode, http);
}
void ReplaceById(int id, String newData)
{
HTTPClient http;
http.begin(ApiHost + "/item/" + id);
http.addHeader("Content-Type", "application/json");
String message = "";
StaticJsonDocument<300> jsonDoc;
jsonDoc["data"] = newData;
serializeJson(jsonDoc, message);
int httpCode = http.PUT(message);
processResponse(httpCode, http);
}
void UpdateById(int id, String newData)
{
HTTPClient http;
http.begin(ApiHost + "/item/" + id);
http.addHeader("Content-Type", "application/json");
String message = "";
StaticJsonDocument<300> jsonDoc;
jsonDoc["data"] = newData;
serializeJson(jsonDoc, message);
int httpCode = http.PATCH(message);
processResponse(httpCode, http);
}
void DeleteById(int id)
{
HTTPClient http;
http.begin(ApiHost + "/item/" + id);
int httpCode = http.sendRequest("DELETE");
processResponse(httpCode, http);
}
In this example, for simplicity, we execute the functions in the ‘Setup’ so they run only once to illustrate their use. Of course, in a project, we would call them where needed in our code.
Result
If we run the code, we will see that all requests to the REST API served on our NodeJS server are executed correctly, and we are getting the responses sent by the server.

We also verify that in the NodeJS server console we are receiving the requests.

It wasn’t too complicated, was it? Now we know how to interact with the ESP8266 as a client, with a REST API in a correct and standardized way.
In the next one, we will add “the icing on the cake” by seeing how to serve a REST API from the ESP8266 itself. This is starting to get interesting! See you soon.
Download the Code
All the code from this post is available for download on Github.
Version for ESP8266: https://github.com/luisllamasbinaburo/ESP8266-Examples
Version for ESP32: https://github.com/luisllamasbinaburo/ESP32-Examples

