Skip to main content
This is a usage example, not a published package. cpp/ in the repo contains a single-header helper (client.hpp) that wraps CPR and nlohmann/json. Copy it into your project or pull it via CMake FetchContent — there is no package to install from a registry. If you’re building in C++, the API is straightforward HTTP with JSON. You can use any HTTP client you already have; the header is just a convenience wrapper.

Pull into your CMake project

include(FetchContent)
FetchContent_Declare(
  sf_voice
  GIT_REPOSITORY https://github.com/sf-voice/sf-voice-core
  GIT_TAG        main
  SOURCE_SUBDIR  cpp
)
FetchContent_MakeAvailable(sf_voice)

target_link_libraries(your_target PRIVATE sf_voice)
Or copy cpp/include/sf_voice/client.hpp directly. You need CPR and nlohmann/json on your include path either way.

Create a client

#include <sf_voice/client.hpp>

sfvoice::SfVoiceMedia client(
    "https://api.sf-voice.com",
    std::getenv("SF_VOICE_API_KEY")
);

Ingest

sfvoice::IngestRequest req;
req.source      = "url";
req.asset_id    = "call_001";
req.asset_class = "customer_acme";
req.url         = "https://storage.example.com/calls/001.mp3";
req.media_type  = "audio";
req.types       = {"audio", "transcript"};

auto result = client.ingest(req).get();

if (!result) {
    std::cerr << result.error().message << "\n";
    return;
}

auto task_id = result.value().task_id;

Poll until ready

auto task = client.poll_task(task_id).get();

if (!task) {
    std::cerr << task.error().message << "\n";
    return;
}

if (task.value().status == "failed") {
    std::cerr << "indexing failed\n";
}
sfvoice::SearchRequest req;
req.query       = "customer asks about pricing";
req.asset_class = "customer_acme";
req.types       = {"transcript"};
req.threshold   = 0.7f;

auto result = client.search(req).get();

if (result) {
    for (const auto& r : result.value().results) {
        std::cout << r.asset_id << " "
                  << r.start_ms << "–" << r.end_ms << "ms\n";
    }
}

Result type

All methods return std::future<Result<T>>. Result<T> is a tagged union — check before use:
if (result) {
    // result.value() — the response
} else {
    // result.error().code, result.error().message, result.error().status
}