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.
| Parameter | Type | Description |
|---|---|---|
api_key | const char* | Your Plexus API key (e.g., "plx_xxxxx") |
source_id | const 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.
| Parameter | Type | Description |
|---|---|---|
buf | void* | Pre-allocated buffer |
buf_size | size_t | Size of the buffer |
api_key | const char* | Your Plexus API key |
source_id | const 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
| Value | Name | Description |
|---|---|---|
| 0 | PLEXUS_OK | Success |
| 1 | PLEXUS_ERR_NULL_PTR | Null pointer argument |
| 2 | PLEXUS_ERR_BUFFER_FULL | Metric buffer full |
| 3 | PLEXUS_ERR_STRING_TOO_LONG | String exceeds max length |
| 4 | PLEXUS_ERR_NO_DATA | No data to flush |
| 5 | PLEXUS_ERR_NETWORK | Network or HTTP error |
| 6 | PLEXUS_ERR_AUTH | Authentication failed (401) |
| 7 | PLEXUS_ERR_FORBIDDEN | Forbidden (403) |
| 8 | PLEXUS_ERR_BILLING | Billing limit exceeded (402) |
| 9 | PLEXUS_ERR_RATE_LIMIT | Rate limited (429) |
| 10 | PLEXUS_ERR_SERVER | Server error (5xx) |
| 11 | PLEXUS_ERR_JSON | JSON serialization error |
| 12 | PLEXUS_ERR_NOT_INITIALIZED | Client not initialized |
| 13 | PLEXUS_ERR_HAL | HAL layer error |
| 14 | PLEXUS_ERR_INVALID_ARG | Invalid argument |
Next Steps
- ESP32 Guide -- Full walkthrough with WiFi and NTP setup
- Memory Configuration -- Tune buffer sizes and RAM usage
- Arduino Guide -- Use the SDK with Arduino
- STM32 Guide -- Use the SDK with STM32 and FreeRTOS