Free Shipping over ₹1299

Lesson 5: API Keys & Connectivity Test

Now that our hardware (Microphone, Speaker, SD Card) is verified, we need to give our ESP32 the “keys” to access the AI brains in the cloud. Without valid credentials, the sophisticated code we write later will just be rejected by the servers.

This lesson focuses on acquiring your API Keys and running a connectivity test using the robust code you provided.

Getting Your Credentials

We need three specific strings of text to make this work. Treat these like passwords—never share them publicly.

A. OpenAI API Key (The Brain)

  1. Go to platform.openai.com and log in.
  2. Click on Dashboard -> API Keys in the left menu.
  3. Click + Create new secret key.
  4. Name it (e.g., “ESP32 Assistant”) and copy the string starting with sk-....
    • Note: You must have a small credit balance (e.g., $5) in your OpenAI account for this to work. It is not free.

B. ElevenLabs API Key (The Voice)

  1. Go to elevenlabs.io and log in.
  2. Click on your Profile Icon (top right) -> Profile + API Key.
  3. Click the “Eye” icon to reveal your API Key and copy it.

C. ElevenLabs Voice ID

  1. Go to the VoiceLab tab.
  2. Choose a voice (e.g., “Adam” or a cloned voice).
  3. Click the ID label or the copy icon next to the voice name to copy the Voice ID (a short string of random characters).

The Connectivity Test Code

This code acts as a “sanity check.” It connects to Wi-Fi, sends a simple “Hello” to ChatGPT, and requests a sample audio file from ElevenLabs. If this passes, your credentials are valid.

Prerequisite: You must install the ArduinoJson library via the Library Manager in Arduino IDE.

#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>  // Proper JSON library

// ============ CONFIG - UPDATE THESE! ============
const char* WIFI_SSID = "YOUR_SSID";
const char* WIFI_PASSWORD = "YOUR_PASSWORD";

// API Keys
const char* OPENAI_API_KEY = "sk-proj-siqa2E7Qx";
const char* ELEVENLABS_API_KEY = "sk_1f3a72616";
const char* VOICE_ID = "21m00Tcm4TlvDq8ikWAM";

// ============ SIMPLE TEST ============
void setup() {
  Serial.begin(115200);
  delay(2000);
  
  Serial.println("\n\n╔══════════════════════════════╗");
  Serial.println(  "║   PROPER API TEST - START    ║");
  Serial.println(  "╚══════════════════════════════╝\n");
  
  Serial.println("Using ArduinoJson v6 for proper parsing");
  
  // 1. Connect to WiFi
  Serial.println("📶 STEP 1: Connecting to WiFi...");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  
  int wifiAttempts = 0;
  while (WiFi.status() != WL_CONNECTED && wifiAttempts < 20) {
    delay(500);
    Serial.print(".");
    wifiAttempts++;
  }
  
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("\n❌ WiFi Failed! Check credentials");
    while(1);
  }
  
  Serial.println("\n✅ WiFi Connected!");
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());
  Serial.printf("Free Heap: %d bytes\n", ESP.getFreeHeap());
  
  // 2. Test OpenAI with proper JSON parsing
  Serial.println("\n🤖 STEP 2: Testing OpenAI (with ArduinoJson)...");
  testOpenAI();
  
  // 3. Test ElevenLabs
  Serial.println("\n🎵 STEP 3: Testing ElevenLabs...");
  testElevenLabs();
  
  
  Serial.println("\n\n╔══════════════════════════════╗");
  Serial.println(  "║     ALL TESTS COMPLETE!     ║");
  Serial.println(  "╚══════════════════════════════╝\n");
}

void loop() {
  // Nothing to do here
  delay(1000);
}

// ============ TEST FUNCTIONS WITH ARDUINOJSON ============
void testOpenAI() {
  Serial.println("  Asking ChatGPT: 'How are you?'");
  
  HTTPClient http;
  http.begin("https://api.openai.com/v1/chat/completions");
  http.addHeader("Authorization", "Bearer " + String(OPENAI_API_KEY));
  http.addHeader("Content-Type", "application/json");
  
  // Create JSON payload with ArduinoJson
  StaticJsonDocument<512> requestDoc;
  requestDoc["model"] = "gpt-3.5-turbo";
  
  JsonArray messages = requestDoc.createNestedArray("messages");
  JsonObject message = messages.createNestedObject();
  message["role"] = "user";
  message["content"] = "How are you?";
  
  requestDoc["max_tokens"] = 30;
  requestDoc["temperature"] = 0.7;
  
  String requestPayload;
  serializeJson(requestDoc, requestPayload);
  
  Serial.println("  Sending request...");
  int httpCode = http.POST(requestPayload);
  
  if (httpCode == 200) {
    String response = http.getString();
    Serial.println("  ✅ Got response from OpenAI");
    
    // Parse response with ArduinoJson
    StaticJsonDocument<2048> responseDoc;
    DeserializationError error = deserializeJson(responseDoc, response);
    
    if (error) {
      Serial.print("  ❌ JSON parse failed: ");
      Serial.println(error.c_str());
      Serial.println("  Raw response (first 500 chars):");
      Serial.println(response.substring(0, 500));
    } else {
      // Extract the reply properly
      if (responseDoc.containsKey("choices") && 
          responseDoc["choices"].is<JsonArray>() && 
          responseDoc["choices"].size() > 0) {
        
        JsonObject choice = responseDoc["choices"][0];
        if (choice.containsKey("message") && 
            choice["message"].is<JsonObject>()) {
          
          JsonObject messageObj = choice["message"];
          if (messageObj.containsKey("content")) {
            String reply = messageObj["content"].as<String>();
            reply.trim();
            
            Serial.print("  ✅ ChatGPT says: \"");
            Serial.print(reply);
            Serial.println("\"");
            
            Serial.println("  ✅ OpenAI API is working perfectly!");
          } else {
            Serial.println("  ❌ No 'content' field in response");
          }
        } else {
          Serial.println("  ❌ No 'message' field in response");
        }
      } else {
        Serial.println("  ❌ No 'choices' array in response");
      }
    }
  } else if (httpCode == 401) {
    Serial.println("  ❌ OpenAI API Key Invalid! (401 Unauthorized)");
  } else if (httpCode == 429) {
    Serial.println("  ⚠️  Rate Limited - try again later (429)");
  } else {
    Serial.print("  ❌ Error: HTTP ");
    Serial.println(httpCode);
    Serial.print("  Error: ");
    Serial.println(http.errorToString(httpCode));
  }
  
  http.end();
}

void testElevenLabs() {
  Serial.println("  Testing TTS with text: 'Hello from ElevenLabs'");
  
  HTTPClient http;
  String url = "https://api.elevenlabs.io/v1/text-to-speech/" + String(VOICE_ID);
  http.begin(url);
  http.addHeader("xi-api-key", ELEVENLABS_API_KEY);
  http.addHeader("Content-Type", "application/json");
  http.addHeader("Accept", "audio/mpeg");
  
  // Create payload with ArduinoJson
  StaticJsonDocument<512> requestDoc;
  requestDoc["text"] = "Hello from ElevenLabs. This is a test.";
  requestDoc["model_id"] = "eleven_multilingual_v2";
  
  JsonObject voiceSettings = requestDoc.createNestedObject("voice_settings");
  voiceSettings["stability"] = 0.5;
  voiceSettings["similarity_boost"] = 0.5;
  
  String requestPayload;
  serializeJson(requestDoc, requestPayload);
  
  Serial.println("  Sending TTS request...");
  int httpCode = http.POST(requestPayload);
  
  if (httpCode == 200) {
    int size = http.getSize();
    if (size > 0) {
      Serial.print("  ✅ ElevenLabs TTS Working! ");
      Serial.print(size);
      Serial.println(" bytes received");      
    }
  } else if (httpCode == 401) {
    Serial.println("  ❌ ElevenLabs API Key Invalid! (401)");
    
    // Try to get error message
    String response = http.getString();
    if (response.length() > 0) {
      StaticJsonDocument<512> errorDoc;
      DeserializationError error = deserializeJson(errorDoc, response);
      if (!error && errorDoc.containsKey("detail")) {
        String detail = errorDoc["detail"]["message"].as<String>();
        Serial.print("  Error detail: ");
        Serial.println(detail);
      }
    }
  } else if (httpCode == 404) {
    Serial.println("  ❌ Voice ID not found! (404)");
    Serial.print("  Voice ID: ");
    Serial.println(VOICE_ID);
  } else {
    Serial.print("  ❌ Error: HTTP ");
    Serial.println(httpCode);
    
    // Try to parse error response
    String response = http.getString();
    if (response.length() > 0) {
      Serial.println("  Response: " + response);
      
      // Try to parse as JSON for better error message
      StaticJsonDocument<512> errorDoc;
      DeserializationError error = deserializeJson(errorDoc, response);
      if (!error) {
        if (errorDoc.containsKey("detail")) {
          if (errorDoc["detail"].is<JsonObject>()) {
            JsonObject detail = errorDoc["detail"];
            if (detail.containsKey("message")) {
              Serial.print("  Error message: ");
              Serial.println(detail["message"].as<String>());
            }
          } else if (errorDoc["detail"].is<String>()) {
            Serial.print("  Error detail: ");
            Serial.println(errorDoc["detail"].as<String>());
          }
        }
      }
    }
  }
  
  http.end();
}


Upload the code and watch the Serial Monitor (115200 baud).

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    Need Help?