C Language Examples - uncloseai.com API

Overview

This example demonstrates how to interact with uncloseai.com API endpoints using C and libcurl. It covers three core functionalities:

Why C? C provides direct control over memory and network operations, making it ideal for understanding low-level HTTP communication and building high-performance API clients.

Prerequisites

The implementation uses libcurl for HTTP requests. In Alpine Linux:

apk add gcc musl-dev curl-dev make
Docker Image: alpine:3.21 (checked 2025-10-12)
libcurl: System package via apk (8.14.1-r2 in Alpine 3.21)

Code Examples

Example 1: Hermes AI Chat

Endpoint: https://hermes.ai.unturf.com/v1/chat/completions
Model: adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic
// Construct JSON request payload
const char *hermes_json = "{"
    "\"model\":\"adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic\","
    "\"messages\":[{\"role\":\"user\",\"content\":\"Give a C function to check if a number is prime\"}],"
    "\"temperature\":0.5,"
    "\"max_tokens\":150"
    "}";

// Make POST request with libcurl
struct MemoryStruct chunk = {NULL, 0};
chunk.memory = malloc(1);
chunk.size = 0;

if(post_request("https://hermes.ai.unturf.com/v1/chat/completions",
                hermes_json, &chunk) == 0) {
    printf("Response received (%zu bytes)\n", chunk.size);
}
free(chunk.memory);

Example 2: Qwen 3 Coder

Endpoint: https://qwen.ai.unturf.com/v1/chat/completions
Model: hf.co/unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF:Q4_K_M
const char *qwen_json = "{"
    "\"model\":\"hf.co/unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF:Q4_K_M\","
    "\"messages\":[{\"role\":\"user\",\"content\":\"Write a C function to reverse a string in place\"}],"
    "\"temperature\":0.5,"
    "\"max_tokens\":200"
    "}";

struct MemoryStruct chunk = {NULL, 0};
chunk.memory = malloc(1);
chunk.size = 0;

if(post_request("https://qwen.ai.unturf.com/v1/chat/completions",
                qwen_json, &chunk) == 0) {
    printf("Response received (%zu bytes)\n", chunk.size);
}
free(chunk.memory);

Example 3: Text-to-Speech

Endpoint: https://speech.ai.unturf.com/v1/audio/speech
Model: tts-1
const char *tts_json = "{"
    "\"model\":\"tts-1\","
    "\"voice\":\"alloy\","
    "\"input\":\"Hello from C with libcurl!\""
    "}";

CURL *curl = curl_easy_init();
if(curl) {
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "Content-Type: application/json");
    headers = curl_slist_append(headers, "Authorization: Bearer YOLO");

    struct MemoryStruct chunk = {NULL, 0};
    chunk.memory = malloc(1);
    chunk.size = 0;

    curl_easy_setopt(curl, CURLOPT_URL, "https://speech.ai.unturf.com/v1/audio/speech");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, tts_json);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);

    CURLcode res = curl_easy_perform(curl);

    if(res == CURLE_OK) {
        FILE *fp = fopen("speech.mp3", "wb");
        if(fp) {
            fwrite(chunk.memory, 1, chunk.size, fp);
            fclose(fp);
            printf("Speech file created: speech.mp3\n");
        }
    }

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    free(chunk.memory);
}

Code Walkthrough

Memory Management for HTTP Responses

struct MemoryStruct {
    char *memory;
    size_t size;
};

static size_t WriteMemoryCallback(void *contents, size_t size,
                                   size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    struct MemoryStruct *mem = (struct MemoryStruct *)userp;

    char *ptr = realloc(mem->memory, mem->size + realsize + 1);
    if(!ptr) {
        printf("Not enough memory\n");
        return 0;
    }

    mem->memory = ptr;
    memcpy(&(mem->memory[mem->size]), contents, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;

    return realsize;
}

Key points:

Reusable POST Request Function

int post_request(const char *url, const char *json_data,
                 struct MemoryStruct *chunk) {
    CURL *curl;
    CURLcode res;
    struct curl_slist *headers = NULL;

    curl = curl_easy_init();
    if(!curl) return -1;

    // Set Content-Type and Authorization headers
    headers = curl_slist_append(headers, "Content-Type: application/json");
    headers = curl_slist_append(headers, "Authorization: Bearer dummy-key");

    // Configure curl options
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)chunk);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);

    res = curl_easy_perform(curl);

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);

    return (res == CURLE_OK) ? 0 : -1;
}

Key points:

Global libcurl Initialization

int main(void) {
    // Initialize libcurl globally (once per process)
    curl_global_init(CURL_GLOBAL_ALL);

    // ... make API calls ...

    // Cleanup libcurl globally before exit
    curl_global_cleanup();
    return 0;
}

Key points:

Running the Examples

Build with Docker

docker build -t ai-unturf-c languages/c/
docker run --rm ai-unturf-c

Build Locally

# Install dependencies (Alpine Linux)
apk add gcc musl-dev curl-dev make

# Compile
make

# Run
./examples
Expected Output:
- Hermes AI: ~1158 bytes JSON response
- Qwen Coder: ~1180 bytes JSON response
- TTS: speech.mp3 file (~30KB MP3 audio)

Common Issues

Missing libcurl

# Alpine Linux
apk add curl-dev

# Debian/Ubuntu
apt-get install libcurl4-openssl-dev

# macOS
brew install curl

SSL/TLS Certificate Errors

If you see SSL verification errors, ensure ca-certificates is installed:
apk add ca-certificates

Compilation Errors

Ensure you're linking against libcurl:

gcc -o examples examples.c -lcurl

The -lcurl flag must come after the source file.

Memory Leaks

Always free allocated memory:

JSON Parsing (Advanced)

This example demonstrates raw HTTP communication. For production use, add JSON parsing:

Recommended JSON libraries for C:

Example with cJSON:

#include <cjson/cJSON.h>

// After receiving response in chunk.memory:
cJSON *json = cJSON_Parse(chunk.memory);
if(json) {
    cJSON *choices = cJSON_GetObjectItem(json, "choices");
    cJSON *first_choice = cJSON_GetArrayItem(choices, 0);
    cJSON *message = cJSON_GetObjectItem(first_choice, "message");
    cJSON *content = cJSON_GetObjectItem(message, "content");

    printf("AI Response: %s\n", content->valuestring);

    cJSON_Delete(json);
}

Implementation Notes

Why This Approach?

Production Considerations

Docker Image Choice

Base Image: alpine:3.21
We use Alpine Linux for minimal size and security. The apk package manager provides all necessary build tools and libcurl development files.

Related Examples