
# C++

Start with the [REST guide](../rest.md) to get a Platform API token. This example uses [libcurl](https://curl.se/libcurl/c/libcurl.html) for HTTPS and [nlohmann/json](https://github.com/nlohmann/json) for JSON parsing. Install their C++ development packages first.

Save as `main.cc`:

```cpp
#include <cstdlib>
#include <iostream>
#include <stdexcept>
#include <string>

#include <curl/curl.h>
#include <nlohmann/json.hpp>

size_t write_body(char* data, size_t size, size_t count, void* user) {
  auto* body = static_cast<std::string*>(user);
  body->append(data, size * count);
  return size * count;
}

std::string get(CURL* curl, const std::string& url, const std::string& token) {
  std::string body;
  const std::string authorization = "Authorization: Bearer " + token;
  curl_slist* headers = curl_slist_append(nullptr, authorization.c_str());
  curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_body);
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &body);
  curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
  CURLcode result = curl_easy_perform(curl);
  long status = 0;
  curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, nullptr);
  curl_slist_free_all(headers);
  if (result != CURLE_OK) throw std::runtime_error(curl_easy_strerror(result));
  if (status != 200) throw std::runtime_error("API returned HTTP " + std::to_string(status));
  return body;
}

int main() {
  const char* token = std::getenv("CR_RECONSTRUCT_API_TOKEN");
  if (!token || !*token) {
    std::cerr << "Set CR_RECONSTRUCT_API_TOKEN\n";
    return 1;
  }

  curl_global_init(CURL_GLOBAL_DEFAULT);
  CURL* curl = curl_easy_init();
  if (!curl) return 1;
  try {
    const std::string base = "https://reconstruct.dev/api/v1/platform";
    auto page = nlohmann::json::parse(get(curl, base + "/catalogs?pageSize=10", token));
    for (const auto& catalog : page.value("catalogs", nlohmann::json::array())) {
      const std::string id = catalog.at("catalogId").get<std::string>();
      char* escaped = curl_easy_escape(curl, id.c_str(), static_cast<int>(id.size()));
      if (!escaped) throw std::runtime_error("Could not encode catalog ID");
      const std::string path = "/catalogs/" + std::string(escaped);
      curl_free(escaped);
      auto detail = nlohmann::json::parse(get(curl, base + path, token));
      std::cout << detail.at("catalogId").get<std::string>() << ": "
                << detail.value("description", "") << '\n';
    }
    if (page.contains("nextPageToken")) {
      std::cout << "Next page token: "
                << page["nextPageToken"].get<std::string>() << '\n';
    }
  } catch (const std::exception& error) {
    std::cerr << error.what() << '\n';
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return 1;
  }
  curl_easy_cleanup(curl);
  curl_global_cleanup();
}
```

Use this `CMakeLists.txt`:

```cmake
cmake_minimum_required(VERSION 3.16)
project(reconstruct_rest_client LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)

find_package(CURL REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
add_executable(reconstruct_rest_client main.cc)
target_link_libraries(reconstruct_rest_client PRIVATE
  CURL::libcurl nlohmann_json::nlohmann_json)
```

Run `cmake -S . -B build`, then `cmake --build build` and `./build/reconstruct_rest_client`.
