C SDK
API Reference

C API Reference

Complete reference for plexus.h (SDK version 0.5.4). All functions are synchronous and single-threaded unless you enable PLEXUS_ENABLE_THREAD_SAFE.

Initialization

plexus_init()

plexus_client_t* plexus_init(const char* api_key, const char* source_id);

Allocate and initialize a Plexus client on the heap.

ParameterTypeDescription
api_keyconst char*Your Plexus API key (e.g., "plx_xxxxx")
source_idconst char*Device identifier. Lowercase [a-z0-9][a-z0-9._-]*

Returns: Client pointer, or NULL on failure.

Free with plexus_free() when done.

plexus_client_t* px = plexus_init("plx_xxxxx", "esp32-001");
if (!px) {
    // handle error
}

plexus_init_static()

plexus_client_t* plexus_init_static(void* buf, size_t buf_size,
                                    const char* api_key, const char* source_id);

Initialize a client in user-provided memory. No heap allocation. The buffer must be at least sizeof(plexus_client_t) bytes and pointer-aligned.

ParameterTypeDescription
bufvoid*Pre-allocated buffer
buf_sizesize_tSize of the buffer
api_keyconst char*Your Plexus API key
source_idconst char*Device identifier

Returns: Client pointer (== buf on success), or NULL if buffer is too small or misaligned.

PLEXUS_CLIENT_STATIC_BUF(my_buf);
plexus_client_t* px = plexus_init_static(
    &my_buf, sizeof(my_buf), "plx_xxxxx", "stm32-001");

plexus_client_size()

size_t plexus_client_size(void);

Get the required buffer size for plexus_init_static() at runtime. Equivalent to sizeof(plexus_client_t).

plexus_free()

void plexus_free(plexus_client_t* client);

Free a heap-allocated client. Safe to pass NULL. Does not flush -- call plexus_flush() first if you have pending data. On a statically-allocated client, this marks it uninitialized but does not call free().

Static Allocation Helpers

PLEXUS_CLIENT_STATIC_BUF

PLEXUS_CLIENT_STATIC_BUF(name);

Declare a correctly-sized and aligned static buffer for a client. Use with plexus_init_static().

PLEXUS_CLIENT_STATIC_BUF(my_buf);
plexus_client_t* px = plexus_init_static(
    &my_buf, sizeof(my_buf), "plx_xxxxx", "device-001");

PLEXUS_CLIENT_STATIC_SIZE

#define PLEXUS_CLIENT_STATIC_SIZE sizeof(plexus_client_t)

Compile-time size constant. Use when you need to declare a raw byte buffer instead of using PLEXUS_CLIENT_STATIC_BUF:

static uint8_t buf[PLEXUS_CLIENT_STATIC_SIZE];
plexus_client_t* px = plexus_init_static(buf, sizeof(buf), key, id);

Configuration

plexus_set_endpoint()

plexus_err_t plexus_set_endpoint(plexus_client_t* client, const char* endpoint);

Set a custom ingest endpoint URL. Default: https://app.plexus.company/api/ingest.

plexus_set_endpoint(px, "https://custom.domain/api/ingest");

plexus_set_flush_interval()

plexus_err_t plexus_set_flush_interval(plexus_client_t* client, uint32_t interval_ms);

Set the auto-flush time interval used by plexus_tick(). Pass 0 to disable time-based auto-flush. Default: 5000 ms.

plexus_set_flush_count()

plexus_err_t plexus_set_flush_count(plexus_client_t* client, uint16_t count);

Set the auto-flush metric count. When this many metrics are queued, plexus_send_*() triggers a flush automatically. Pass 0 to disable count-based auto-flush. Default: 16.

Sending Metrics

plexus_send() / plexus_send_number()

plexus_err_t plexus_send_number(plexus_client_t* client, const char* metric, double value);
 
// Convenience macro — identical to plexus_send_number()
#define plexus_send(client, metric, value) plexus_send_number((client), (metric), (value))

Queue a numeric metric. Returns PLEXUS_ERR_BUFFER_FULL if the buffer is full.

plexus_send(px, "temperature", 23.5);
plexus_send_number(px, "rpm", 3450.0);

plexus_send_number_ts()

plexus_err_t plexus_send_number_ts(plexus_client_t* client, const char* metric,
                                   double value, uint64_t timestamp_ms);

Queue a numeric metric with an explicit Unix timestamp in milliseconds. Use this when you need precise control over the timestamp (e.g., replaying recorded data).

plexus_send_number_ts(px, "pressure", 1013.25, 1700000000000ULL);

plexus_send_string()

plexus_err_t plexus_send_string(plexus_client_t* client, const char* metric, const char* value);

Queue a string metric. Only available when PLEXUS_ENABLE_STRING_VALUES=1 (on by default).

plexus_send_string(px, "vehicle.state", "RUNNING");

plexus_send_bool()

plexus_err_t plexus_send_bool(plexus_client_t* client, const char* metric, bool value);

Queue a boolean metric. Only available when PLEXUS_ENABLE_BOOL_VALUES=1 (on by default).

plexus_send_bool(px, "motor.enabled", true);

plexus_send_number_tagged()

plexus_err_t plexus_send_number_tagged(plexus_client_t* client, const char* metric,
                                       double value, const char** tag_keys,
                                       const char** tag_values, uint8_t tag_count);

Queue a numeric metric with key-value tags. Only available when PLEXUS_ENABLE_TAGS=1 (on by default). Maximum 4 tags per metric.

const char* keys[]   = {"location", "unit"};
const char* values[] = {"lab-1",    "celsius"};
plexus_send_number_tagged(px, "temperature", 23.5, keys, values, 2);

Flush and Network

plexus_flush()

plexus_err_t plexus_flush(plexus_client_t* client);

Send all queued metrics to the Plexus API immediately. On success, the buffer is cleared. On failure, metrics remain in the buffer for retry.

Blocking behavior: This function retries with exponential backoff on transient errors. Worst case: ~14 seconds (3 retries, 8-second max backoff). On FreeRTOS, the calling task yields during delays. On bare-metal Arduino, delay() blocks the MCU.

plexus_tick()

plexus_err_t plexus_tick(plexus_client_t* client);

Call this periodically from your main loop. Handles time-based auto-flush. Count-based flushing happens automatically in plexus_send_*(). Returns PLEXUS_OK when idle (no flush needed). Only returns an error if a flush actually fails.

while (1) {
    plexus_send(px, "temp", read_temp());
    plexus_tick(px);  // auto-flushes when conditions are met
    vTaskDelay(pdMS_TO_TICKS(1000));
}

plexus_pending_count()

uint16_t plexus_pending_count(const plexus_client_t* client);

Get the number of metrics currently queued in the buffer.

plexus_clear()

void plexus_clear(plexus_client_t* client);

Discard all queued metrics without sending them.

Statistics

plexus_total_sent()

uint32_t plexus_total_sent(const plexus_client_t* client);

Lifetime counter of metrics successfully sent to the API.

plexus_total_errors()

uint32_t plexus_total_errors(const plexus_client_t* client);

Lifetime counter of send errors.

Sessions

plexus_session_start()

plexus_err_t plexus_session_start(plexus_client_t* client, const char* session_id);

Start a recording session. All subsequent metrics include session_id in their JSON payload. Session IDs follow the same lowercase [a-z0-9][a-z0-9._-]* rules as source IDs.

plexus_session_end()

plexus_err_t plexus_session_end(plexus_client_t* client);

End the current session. Subsequent metrics no longer include a session_id.

plexus_session_id()

const char* plexus_session_id(const plexus_client_t* client);

Get the current session ID, or NULL if no session is active.

Connection Status

These functions are only available when PLEXUS_ENABLE_STATUS_CALLBACK=1 (off by default).

plexus_on_status_change()

plexus_err_t plexus_on_status_change(plexus_client_t* client,
                                     plexus_status_callback_t callback,
                                     void* user_data);

Register a callback for connection status changes. The callback fires only on state transitions (not repeated for the same status).

void on_status(plexus_conn_status_t status, void* data) {
    switch (status) {
        case PLEXUS_STATUS_CONNECTED:     printf("Connected\n"); break;
        case PLEXUS_STATUS_DISCONNECTED:  printf("Disconnected\n"); break;
        case PLEXUS_STATUS_AUTH_FAILED:   printf("Auth failed\n"); break;
        case PLEXUS_STATUS_RATE_LIMITED:  printf("Rate limited\n"); break;
    }
}
 
plexus_on_status_change(px, on_status, NULL);

plexus_get_status()

plexus_conn_status_t plexus_get_status(const plexus_client_t* client);

Get the last known connection status.

Utility

plexus_strerror()

const char* plexus_strerror(plexus_err_t err);

Get a human-readable error message for an error code.

plexus_version()

const char* plexus_version(void);

Get the SDK version string (e.g., "0.5.4").

HAL Interface

These functions are implemented per platform (ESP32, STM32, Arduino). You only need to implement them if you are porting the SDK to a new platform.

// HTTP POST — send JSON body to the ingest endpoint
plexus_err_t plexus_hal_http_post(const char* url, const char* api_key,
                                  const char* user_agent,
                                  const char* body, size_t body_len);
 
// Wall-clock time in milliseconds (Unix epoch)
uint64_t plexus_hal_get_time_ms(void);
 
// Monotonic tick counter in milliseconds (for intervals)
uint32_t plexus_hal_get_tick_ms(void);
 
// Blocking delay (should yield on RTOS)
void plexus_hal_delay_ms(uint32_t ms);
 
// Debug logging (only called when PLEXUS_DEBUG=1)
void plexus_hal_log(const char* fmt, ...);

Persistent Buffer HAL (opt-in)

Available when PLEXUS_ENABLE_PERSISTENT_BUFFER=1:

plexus_err_t plexus_hal_storage_write(const char* key, const void* data, size_t len);
plexus_err_t plexus_hal_storage_read(const char* key, void* data, size_t max_len, size_t* out_len);
plexus_err_t plexus_hal_storage_clear(const char* key);

Thread Safety HAL (opt-in)

Available when PLEXUS_ENABLE_THREAD_SAFE=1:

void* plexus_hal_mutex_create(void);
void  plexus_hal_mutex_lock(void* mutex);
void  plexus_hal_mutex_unlock(void* mutex);
void  plexus_hal_mutex_destroy(void* mutex);

Error Codes

ValueNameDescription
0PLEXUS_OKSuccess
1PLEXUS_ERR_NULL_PTRNull pointer argument
2PLEXUS_ERR_BUFFER_FULLMetric buffer full
3PLEXUS_ERR_STRING_TOO_LONGString exceeds max length
4PLEXUS_ERR_NO_DATANo data to flush
5PLEXUS_ERR_NETWORKNetwork or HTTP error
6PLEXUS_ERR_AUTHAuthentication failed (401)
7PLEXUS_ERR_FORBIDDENForbidden (403)
8PLEXUS_ERR_BILLINGBilling limit exceeded (402)
9PLEXUS_ERR_RATE_LIMITRate limited (429)
10PLEXUS_ERR_SERVERServer error (5xx)
11PLEXUS_ERR_JSONJSON serialization error
12PLEXUS_ERR_NOT_INITIALIZEDClient not initialized
13PLEXUS_ERR_HALHAL layer error
14PLEXUS_ERR_INVALID_ARGInvalid argument

Next Steps