ESP32 HTTP POST with Arduino IDE (ThingSpeak and IFTTT.com)

In this guide, you’ll learn how to make HTTP POST requests using the ESP32 board with Arduino IDE. We’ll demonstrate how to post JSON data or URL encoded values to two web APIs (ThingSpeak and IFTTT.com).

ESP32 HTTP POST with Arduino IDE IFTTT ThingSpeak

Recommended: ESP32 HTTP GET with Arduino IDE (OpenWeatherMap.org and ThingSpeak)

HTTP POST Request Method

The Hypertext Transfer Protocol (HTTP) works as a request-response protocol between a client and server. Here’s an example:

  • The ESP32 (client) submits an HTTP request to a Server (for example: ThingSpeak or IFTTT.com);
  • The server returns a response to the ESP32 (client);
  • Finally, the response contains status information about the request and may also contain the requested content.

HTTP POST

POST is used to send data to a server to create/update a resource. For example, publish sensor readings to a server.

The data sent to the server with POST is stored in the request body of the HTTP request:

POST /update HTTP/1.1
Host: example.com
api_key=api&field1=value1
Content-Type: application/x-www-form-urlencoded

In the body request, you can also send a JSON object:

POST /update HTTP/1.1
Host: example.com
{api_key: "api", field1: value1}
Content-Type: application/json

(With HTTP POST, data is not visible in the URL request. However, if it’s not encrypted, it’s still visible in the request body.)

Prerequisites

Before proceeding with this tutorial, make sure you complete the following prerequisites.

Arduino IDE

We’ll program the ESP32 using Arduino IDE, so make sure you have the ESP32 add-on installed.

Other Web Services or APIs

In this guide, you’ll learn how to setup your ESP32 board to perform HTTP requests to ThingSpeak and IFTTT.com. If you prefer to learn with a local solution you can use HTTP with Node-RED. All examples presented in this guide also work with other APIs.

In summary, to make this guide compatible with any service, you need to search for the service API documentation. Then, you need the server name (URL or IP address), and parameters to send in the request (URL path or request body). Finally, modify our examples to integrate with any API you want to use.

1. ESP32 HTTP POST Data (ThingSpeak)

In this example, the ESP32 makes an HTTP POST request to send a new value to ThingSpeak.

HTTP POST ThingSpeak ESP32

Using ThingSpeak API

ThingSpeak has a free API that allows you to store and retrieve data using HTTP. In this tutorial, you’ll use the ThingSpeak API to publish and visualize data in charts from anywhere. As an example, we’ll publish random values, but in a real application you would use real sensor readings.

To use ThingSpeak API, you need an API key. Follow the next steps:

  1. Go to ThingSpeak.com and create a free account.
  2. Then, open the Channels tab.
  3. Create a New Channel.
ESP32 ESP8266 NodeMCU ThingSpeak Create New Channel
  1. Open your newly created channel and select the API Keys tab to copy your Write API Key.
ESP32 ESP8266 NodeMCU ThingSpeak View API Key Write Copy

Code ESP32 HTTP POST ThingSpeak

Copy the next sketch to your Arduino IDE:

/*
  Rui Santos
  Complete project details at Complete project details at https://RandomNerdTutorials.com/esp32-http-post-ifttt-thingspeak-arduino/ 

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Domain Name with full URL Path for HTTP POST Request
const char* serverName = "http://api.thingspeak.com/update";
// Service API Key
String apiKey = "REPLACE_WITH_YOUR_API_KEY";

// THE DEFAULT TIMER IS SET TO 10 SECONDS FOR TESTING PURPOSES
// For a final application, check the API call limits per hour/minute to avoid getting blocked/banned
unsigned long lastTime = 0;
// Set timer to 10 minutes (600000)
//unsigned long timerDelay = 600000;
// Timer set to 10 seconds (10000)
unsigned long timerDelay = 10000;

void setup() {
  Serial.begin(115200);

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
 
  Serial.println("Timer set to 10 seconds (timerDelay variable), it will take 10 seconds before publishing the first reading.");

  // Random seed is a number used to initialize a pseudorandom number generator
  randomSeed(analogRead(33));
}

void loop() {
  //Send an HTTP POST request every 10 seconds
  if ((millis() - lastTime) > timerDelay) {
    //Check WiFi connection status
    if(WiFi.status()== WL_CONNECTED){
      WiFiClient client;
      HTTPClient http;
    
      // Your Domain name with URL path or IP address with path
      http.begin(client, serverName);
      
      // Specify content-type header
      http.addHeader("Content-Type", "application/x-www-form-urlencoded");
      // Data to send with HTTP POST
      String httpRequestData = "api_key=" + apiKey + "&field1=" + String(random(40));           
      // Send HTTP POST request
      int httpResponseCode = http.POST(httpRequestData);
      
      /*
      // If you need an HTTP request with a content type: application/json, use the following:
      http.addHeader("Content-Type", "application/json");
      // JSON data to send with HTTP POST
      String httpRequestData = "{\"api_key\":\"" + apiKey + "\",\"field1\":\"" + String(random(40)) + "\"}";           
      // Send HTTP POST request
      int httpResponseCode = http.POST(httpRequestData);*/
     
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
        
      // Free resources
      http.end();
    }
    else {
      Serial.println("WiFi Disconnected");
    }
    lastTime = millis();
  }
}

View raw code

Setting your network credentials

Modify the next lines with your network credentials: SSID and password. The code is well commented on where you should make the changes.

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Setting your API Key

Modify the apiKey variable to include your ThingSpeak API key.

String apiKey = "REPLACE_WITH_YOUR_API_KEY";

Now, upload the code to your board and it should work straight away. Read the next section, if you want to learn how to make the HTTP POST request.

HTTP POST Request

In the loop() is where you make the HTTP POST request with URL encoded data every 10 seconds with random data:

// Specify content-type header
http.addHeader("Content-Type", "application/x-www-form-urlencoded");

// Data to send with HTTP POST
String httpRequestData = "api_key=" + apiKey + "&field1=" + String(random(40));

// Send HTTP POST request
int httpResponseCode = http.POST(httpRequestData);

For example, the ESP32 makes a URL encoded request to publish a new value (30) to field1.

POST /update HTTP/1.1
Host: api.thingspeak.com
api_key=api&field1=30
Content-Type: application/x-www-form-urlencoded

Or you can uncomment these next lines to make a request with JSON data (instead of URL-encoded request):

// If you need an HTTP request with a content type: application/json, use the following:
http.addHeader("Content-Type", "application/json");

// JSON data to send with HTTP POST
String httpRequestData = "{\"api_key\":\"" + apiKey + "\",\"field1\":\"" + String(random(40)) + "\"}";

// Send HTTP POST request
int httpResponseCode = http.POST(httpRequestData);

Here’s a sample HTTP POST request with JSON data:

POST /update HTTP/1.1
Host: api.thingspeak.com
{api_key: "api", field1: 30}
Content-Type: application/json

Then, the following lines print the server response code.

Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);

In the Arduino IDE serial monitor, you should see an HTTP response code of 200 (this means that the request has succeeded).

ESP32 ESP8266 NodeMCU HTTP POST Arduino IDE Serial Monitor Response

Your ThingSpeak Dashboard should be receiving new random readings every 10 seconds.

ESP32 ESP8266 NodeMCU HTTP GET and HTTP POST with Arduino IDE ThingSpeak Chart

For a final application, you might need to increase the timer or check the API call limits per hour/minute to avoid getting blocked/banned.

2. ESP32 HTTP POST (IFTTT.com)

In this example you’ll learn how to trigger a web API to send email notifications. As an example, we’ll use the IFTTT.com API. IFTTT has has a free plan with lots of useful automations.

HTTP POST IFTTT ESP32

Using IFTTT.com Webhooks API

IFTTT stands for “If This Than That”, and it is a free web-based service to create chains of simple conditional statements called applets.

IFTTT.com logo png

This means you can trigger an event when something happens. In this example, the applet sends three random values to your email when the ESP32 makes a request. You can replace those random values with useful sensor readings.

Creating an IFTTT Account

If you don’t have an IFTTT account, go the IFTTT website: ifttt.com and enter your email to create an account and get started. Creating an account on IFTTT is free!

Next, you need to create a new applet. Follow the next steps to create a new
applet:

1. Open the left menu and click the “Create” button.

ifttt discover create new applet

2. Click on the “this” word. Search for the “Webhooks” service and select the Webhooks icon.

Select webhooks services IFTTT.com

3. Choose the “Receive a web request” trigger and give a name to the event. In this case, I’ve typed “test_event”. Then, click the “Create trigger” button.

4. Click the “that” word to proceed. Now, define what happens when the event you’ve defined is triggered. Search for the “Email” service and select it.

select email service ifttt

5. Then, select Send me an email. You can leave the default options.

6. Press the “Create action” button to create your Applet. Then, click on Continue, and finally, Finish.

Testing Your Applet

Before proceeding with the project, it’s important to test your Applet first. Follow the next steps to test it:

1. Search for Webhooks service or open this link: https://ifttt.com/maker_webhooks

2. Click the “Documentation” button.

webhooks documentation ifttt

A page showing your unique API key will show up.

IFTTT API key

Save your API key because you’ll need it later.

3. Fill the “To trigger an Event with 3 JSON values” section with the event name created previously, in our case test_event. Add some random values to the value1, value2, and value 3 fields. Then, click the “Test it” button.

IFTTT Trigger an Event with 3 JSON values

4. The event should be successfully triggered, and you’ll get a green message saying “Event has been triggered”.

5. Go to your Email account. You should have a new email in your inbox from the IFTTT service with the values you’ve defined in the previous step.

If you’ve received an email with the data entered in the test request, it means your Applet is working as expected. Now, we need to program the ESP32 to send an HTTP POST request to the IFTTT service with the sensor readings.

Code ESP32 HTTP POST Webhooks IFTTT.com

After installing the necessary board add-ons and libraries, copy the following code to your Arduino IDE, but don’t upload it yet. You need to make some changes to make it work for you.

/*
  Rui Santos
  Complete project details at Complete project details at https://RandomNerdTutorials.com/esp32-http-post-ifttt-thingspeak-arduino/

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Domain Name with full URL Path for HTTP POST Request
// REPLACE WITH YOUR EVENT NAME AND API KEY - open the documentation: https://ifttt.com/maker_webhooks
const char* serverName = "http://maker.ifttt.com/trigger/REPLACE_WITH_YOUR_EVENT/with/key/REPLACE_WITH_YOUR_API_KEY";
// Example:
//const char* serverName = "http://maker.ifttt.com/trigger/test_event/with/key/nAZjOphL3d-ZO4N3k64-1A7gTlNSrxMJdmqy3tC";

// THE DEFAULT TIMER IS SET TO 10 SECONDS FOR TESTING PURPOSES
// For a final application, check the API call limits per hour/minute to avoid getting blocked/banned
unsigned long lastTime = 0;
// Set timer to 10 minutes (600000)
//unsigned long timerDelay = 600000;
// Timer set to 10 seconds (10000)
unsigned long timerDelay = 10000;

void setup() {
  Serial.begin(115200);

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
 
  Serial.println("Timer set to 10 seconds (timerDelay variable), it will take 10 seconds before publishing the first reading.");

  // Random seed is a number used to initialize a pseudorandom number generator
  randomSeed(analogRead(33));
}

void loop() {
  //Send an HTTP POST request every 10 seconds
  if ((millis() - lastTime) > timerDelay) {
    //Check WiFi connection status
    if(WiFi.status()== WL_CONNECTED){
      WiFiClient client;
      HTTPClient http;
    
      // Your Domain name with URL path or IP address with path
      http.begin(client, serverName);
      
      // Specify content-type header
      http.addHeader("Content-Type", "application/x-www-form-urlencoded");
      // Data to send with HTTP POST
      String httpRequestData = "value1=" + String(random(40)) + "&value2=" + String(random(40))+ "&value3=" + String(random(40));           
      // Send HTTP POST request
      int httpResponseCode = http.POST(httpRequestData);
      
      /*
      // If you need an HTTP request with a content type: application/json, use the following:
      http.addHeader("Content-Type", "application/json");
      // JSON data to send with HTTP POST
      String httpRequestData = "{\"value1\":\"" + String(random(40)) + "\",\"value2\":\"" + String(random(40)) + "\",\"value3\":\"" + String(random(40)) + "\"}";
      // Send HTTP POST request
      int httpResponseCode = http.POST(httpRequestData);
      */
     
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
        
      // Free resources
      http.end();
    }
    else {
      Serial.println("WiFi Disconnected");
    }
    lastTime = millis();
  }
}

View raw code

Setting your network credentials

Modify the next lines with your network credentials: SSID and password. The code is well commented on where you should make the changes.

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Setting your IFTTT.com API Key

Insert your event name and API key in the following line:

const char* serverName = "http://maker.ifttt.com/trigger/REPLACE_WITH_YOUR_EVENT/with/key/REPLACE_WITH_YOUR_API_KEY";

Example URL:

const char* serverName = "http://maker.ifttt.com/trigger/test_event/with/key/nAZjOphL3d-ZO4N3k64-1A7gTlNSrxMJdmqy3t";

HTTP POST Request

In the loop() is where you make the HTTP POST request every 10 seconds with sample data:

// Specify content-type header
http.addHeader("Content-Type", "application/x-www-form-urlencoded");

// Data to send with HTTP POST
String httpRequestData = "value1=" + String(random(40)) + "&value2=" + String(random(40))+ "&value3=" + String(random(40));

// Send HTTP POST request
int httpResponseCode = http.POST(httpRequestData);

The ESP32 makes a new URL encoded request to publish some random values in the value1, value2 and value3 fields. For example:

POST /trigger/test_event/with/key/nAZjOphL3d-ZO4N3k64-1A7gTlNSrxMJdmqy3tC HTTP/1.1
Host: maker.ifttt.com
value1=15&value2=11&value3=30
Content-Type: application/x-www-form-urlencoded

Alternatively, you can uncomment these next lines to make a request with JSON data:

// If you need an HTTP request with a content type: application/json, use the following:
http.addHeader("Content-Type", "application/json");

// JSON data to send with HTTP POST
String httpRequestData = "{\"value1\":\"" + String(random(40)) + "\",\"value2\":\"" + String(random(40)) + "\",\"value3\":\"" + String(random(40)) + "\"}";

// Send HTTP POST request
int httpResponseCode = http.POST(httpRequestData);

Here’s an example of HTTP POST request with a JSON data object.

POST /trigger/test_event/with/key/nAZjOphL3d-ZO4N3k64-1A7gTlNSrxMJdmqy3tC HTTP/1.1
Host: maker.ifttt.com
{value1: 15, value2: 11, value3: 30}
Content-Type: application/json

Then, the following lines of code print the HTTP response from the server.

Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);

HTTP POST Demonstration

After uploading the code, open the Serial Monitor and you’ll see a message printing the HTTP response code 200 indicating that the request has succeeded.

ESP32 ESP8266 NodeMCU HTTP POST Arduino IDE Serial Monitor Response

Go to your email account, and you should get a new email from IFTTT with three random values. In this case: 38, 20 and 13.

ESP32 ESP8266 NodeMCU HTTP POST Arduino IDE IFTTT Response

For demonstration purposes, we’re publishing new data every 10 seconds. However, for a long term project you should increase the timer or check the API call limits per hour/minute to avoid getting blocked/banned.

Wrapping Up

In this tutorial you’ve learned how to integrate your ESP32 with web services using HTTP POST requests. You can also make HTTP GET requests with the ESP32.

If you’re using an ESP8266 board, read:

You might also like reading:

I hope you liked this project. If you have any questions, post a comment below and we’ll try to get back to you.

If you like ESP32, you might consider enrolling in our course “Learn ESP32 with Arduino IDE“. You can also access our free ESP32 resources here.

Thank you for reading.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

16 thoughts on “ESP32 HTTP POST with Arduino IDE (ThingSpeak and IFTTT.com)”

  1. When I POST single whole string it’s working ok….but when I create String using += Operator it’s not POST . Server returns 200 .

    Reply
  2. Does gmail work with IFTTT? I set everything up and test in IFTTT. It doesn’t complain but I never get an email.

    Reply
    • Hi Steve.
      Yes, it works.
      Double-check that you have the right event name in the URL as well as the API key.
      Did you go to the documentation tab and test the applet?
      Regards,
      Sara

      Reply
      • Thanks for the response Sara. Yes I’ve double checked and tested using the documentation tab. (I assume it auto-populates with the correct API key.) I get the notification that the applet ran but the email never shows up. I’ve checked spam and filters and don’t see anything wrong with my gmail account but there must be if it works for others.

        Reply
  3. Hi

    Thank you for your tutorials, it has taught me so much.

    I have a project that uses asysnc web server libraries for posting sensor data and controlling relays. When I tried to add Thingspeak libraries to my project, it caused a massive amount of errors and it seems that the Thingspeak libraries and the Async libraries don’t like to be used together.

    Do you know of a way to add Thingspeak functionality to an Async web server project?

    Reply
    • Sorry, I see now that this example does not use the Thingspeak libraries and might solve my problem. I will give it a try.

      Can the HTTPClient be used together with an Async Web Server?

      Reply
  4. I tried to load this ,I keep getting an error about HTTPClient ,noticed that it expected HttpClient so I changed that but still get error. No matching function, went to github and downloaded HttpClient master, installed it as a zip in include library but still issues.Help please

    Reply
  5. /*
    Rui Santos
    Complete project details at Complete project details at https://RandomNerdTutorials.com/esp32-http-post-ifttt-thingspeak-arduino/

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files.

    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.
    */

    #include <WiFi.h>
    #include <HttpClient.h>

    char* ssid = “NETGEAR18”;
    char* password = “crispybox986”;

    // Domain Name with full URL Path for HTTP POST Request
    const char* serverName = “http://api.thingspeak.com/update”;
    // Service API Key
    String apiKey = “161866”;

    // THE DEFAULT TIMER IS SET TO 10 SECONDS FOR TESTING PURPOSES
    // For a final application, check the API call limits per hour/minute to avoid getting blocked/banned
    unsigned long lastTime = 0;
    // Set timer to 10 minutes (600000)
    //unsigned long timerDelay = 600000;
    // Timer set to 10 seconds (10000)
    unsigned long timerDelay = 10000;

    void setup() {
    Serial.begin(115200);

    WiFi.begin(ssid, password);
    Serial.println(“Connecting”);
    while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(“.”);
    }
    Serial.println(“”);
    Serial.print(“Connected to WiFi network with IP Address: “);
    Serial.println(WiFi.localIP());
    // Serial.print(“ESP Board MAC Address: “);
    // Serial.println(WiFi.macAddress());
    Serial.println(“Timer set to 10 seconds (timerDelay variable), it will take 10 seconds before publishing the first reading.”);

    // Random seed is a number used to initialize a pseudorandom number generator
    randomSeed(analogRead(33));
    }

    void loop() {
    //Send an HTTP POST request every 10 seconds
    if ((millis() – lastTime) > timerDelay) {
    //Check WiFi connection status
    if(WiFi.status()== WL_CONNECTED){
    HttpClient http; //here is where I get the error of no matching function for call to HttpClient :: HttpClient

    // Your Domain name with URL path or IP address with path
    http.begin(serverName);

    // Specify content-type header
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
    // Data to send with HTTP POST
    String httpRequestData = "api_key=" + apiKey + "&field1=" + String(random(40));
    // Send HTTP POST request
    int httpResponseCode = http.POST(httpRequestData);

    /*
    // If you need an HTTP request with a content type: application/json, use the following:
    http.addHeader("Content-Type", "application/json");
    // JSON data to send with HTTP POST
    String httpRequestData = "{\"api_key\":\"" + apiKey + "\",\"field1\":\"" + String(random(40)) + "\"}";
    // Send HTTP POST request
    int httpResponseCode = http.POST(httpRequestData);*/

    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);

    // Free resources
    http.end();
    }
    else {
    Serial.println("WiFi Disconnected");
    }
    lastTime = millis();

    }
    }

    Reply
  6. Hi. I just did the example with ThingSpeak and i am getting the following message “HTTP Response code: -1”. What does it mean and how can i fix it?

    Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.