SendAfrica logoSendAfricaDocs

C++ SDK

Modern C++17 client built on libcurl and nlohmann/json — CMake FetchContent, vcpkg, or Conan; HMAC webhook verification via OpenSSL.


Versionv1.0.1 · stable
RequiresC++17 (GCC 8+/Clang 7+/MSVC 2019+), CMake 3.16+, libcurl 7.75+, OpenSSL 3.0+
Dependencieslibcurl (HTTP), nlohmann/json (auto-fetched), OpenSSL (HMAC)
InstallCMake FetchContent · vcpkg · Conan

#Installation

CMakeLists.txt
cpp
# CMake FetchContent (recommended)
include(FetchContent)
FetchContent_Declare(sendafrica
    GIT_REPOSITORY https://github.com/SendAfrica/SendAfrica-cpp-sdk.git
    GIT_TAG        v1.0.1
)
FetchContent_MakeAvailable(sendafrica)
target_link_libraries(your_app PRIVATE sendafrica::sendafrica)

# vcpkg
vcpkg install sendafrica

# Conan
conan install sendafrica/1.0.1@ --build=missing

# System deps (Debian/Ubuntu)
# sudo apt-get install cmake g++ libcurl4-openssl-dev libssl-dev

#Client setup

auth.cpp
cpp
#include <sendafrica/sendafrica.hpp>

// Option 1: explicit key
sendafrica::Client client("SA-xxxxx");

// Option 2: set env var, then no arguments needed
// export SENDAFRICA_API_KEY="SA-xxxxx"
sendafrica::Client client;

// Full configuration
sendafrica::ClientOptions opts;
opts.timeout_seconds = 30;      // default 10
opts.max_retries = 5;           // default 3
opts.debug = true;              // log to stderr
opts.webhook_secret = "whsec_...";
sendafrica::Client client("SA-xxxxx", opts);

#Sending SMS

send.cpp
cpp
#include <sendafrica/sendafrica.hpp>
#include <iostream>

int main() {
    sendafrica::Client client("SA-xxxxx");

    auto result = client.sms().send(
        "0712345678",
        "Your OTP is 123456",
        "MyBrand"  // optional, max 11 chars
    );

    std::cout << result.message_id << "\n";    // "SA-xxxx-xxxx-xxxx"
    std::cout << result.status << "\n";        // "sent"
    std::cout << result.credits_used << "\n";  // 1

    // Preview cost without sending (zero network calls)
    auto analysis = client.sms().analyze("Habari, how are you?");
    std::cout << analysis.encoding << ": " << analysis.parts << "\n";
}

#Bulk sending

bulk.cpp
cpp
std::vector<sendafrica::SMSResource::BulkItem> items = {
    {"+255711111111", "Hello John"},
    {"+255722222222", "Hello Mary"},
};

auto bulk = client.sms().send_many(items, "MyBrand");
std::cout << bulk.sent_count() << " sent\n";

for (const auto& f : bulk.failed) {
    std::cerr << "Index " << f.index << " (" << f.to << "): "
              << f.error << "\n";
}

#Delivery status & credits

status.cpp
cpp
auto result = client.sms().send("0712345678", "Hello!");
// ... later ...
auto status = client.sms().status(result.message_id);
std::cout << status.status << "\n";  // "delivered"

auto balance = client.credits().balance();
std::cout << balance.balance << " credits\n";

auto txns = client.credits().history(1, 50);
for (const auto& tx : txns) {
    std::cout << tx.id << " " << tx.type << " " << tx.amount << "\n";
}

#Webhooks & errors

webhooks.cpp
cpp
// In your HTTP handler:
std::string raw_body   = /* request body */;
std::string sig_header = /* X-SendAfrica-Signature header */;

auto event = client.webhooks().parse(raw_body, sig_header);
if (event.type == "sms.delivered") {
    std::cout << "Delivered: " << *event.message_id << "\n";
}

try {
    client.sms().send("0712345678", "Hello");
} catch (const sendafrica::InsufficientCreditsError& e) {
    std::cerr << "Not enough credits\n";
} catch (const sendafrica::RateLimitError& e) {
    std::cerr << "Rate limited, retry after " << *e.retry_after() << "s\n";
} catch (const sendafrica::Error& e) {
    std::cerr << e.message() << " (HTTP " << *e.status_code() << ")\n";
}