Tutorials & SDKs

Java Integration

Use Hive from JVM services with Java HttpClient.

Requirements: Java 11+


Dependencies

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.17.0</version>
</dependency>

Quick Start

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Map;

public class HiveExample {
    private static final String BASE_URL = "https://mcp.hiveintelligence.xyz";

    public static void main(String[] args) throws Exception {
        String apiKey = System.getenv("HIVE_API_KEY");
        ObjectMapper mapper = new ObjectMapper();

        Map<String, Object> payload = Map.of(
            "tool", "get_price",
            "args", Map.of("ids", "bitcoin", "vs_currencies", "usd")
        );

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(BASE_URL + "/api/v1/execute"))
            .header("Content-Type", "application/json")
            .header("Authorization", "Bearer " + apiKey)
            .POST(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(payload)))
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());

        System.out.println(response.body());
    }
}

Reusable Client

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Map;

public class HiveClient {
    private final String baseUrl;
    private final String apiKey;
    private final HttpClient httpClient;
    private final ObjectMapper objectMapper;

    public HiveClient(String apiKey) {
        this.baseUrl = "https://mcp.hiveintelligence.xyz";
        this.apiKey = apiKey;
        this.httpClient = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(30))
            .build();
        this.objectMapper = new ObjectMapper();
    }

    public Map<String, Object> execute(String tool, Map<String, Object> args) throws Exception {
        Map<String, Object> payload = Map.of(
            "tool", tool,
            "args", args
        );

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + "/api/v1/execute"))
            .header("Content-Type", "application/json")
            .header("Authorization", "Bearer " + apiKey)
            .POST(HttpRequest.BodyPublishers.ofString(objectMapper.writeValueAsString(payload)))
            .build();

        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() >= 300) {
            throw new RuntimeException("Hive request failed: " + response.body());
        }

        return objectMapper.readValue(response.body(), Map.class);
    }
}

Discovery

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://mcp.hiveintelligence.xyz/api/v1/tools?limit=50"))
    .header("Authorization", "Bearer " + System.getenv("HIVE_API_KEY"))
    .GET()
    .build();

Example Calls

HiveClient client = new HiveClient(System.getenv("HIVE_API_KEY"));

Map<String, Object> market = client.execute("get_coins_market_data", Map.of(
    "vs_currency", "usd",
    "order", "market_cap_desc",
    "per_page", 5
));

Map<String, Object> wallet = client.execute("moralis_get_wallet_net_worth", Map.of(
    "address", "0x1234...",
    "chain", "eth"
));

Map<String, Object> prediction = client.execute("codex_prediction_markets", Map.of(
    "networkId", 1
));

Error Handling

Hive returns a JSON envelope on every response. Non-2xx bodies carry a structured error object — parse it before retrying:

import com.fasterxml.jackson.databind.JsonNode;

public class HiveException extends RuntimeException {
    public final int httpStatus;
    public final String code;
    public HiveException(int httpStatus, String code, String message) {
        super(code + ": " + message);
        this.httpStatus = httpStatus;
        this.code = code;
    }
}

private Map<String, Object> executeWithRetry(String tool, Map<String, Object> args, int maxRetries)
        throws Exception {
    Exception last = null;
    for (int attempt = 0; attempt < maxRetries; attempt++) {
        try {
            HttpResponse<String> response = httpClient.send(buildRequest(tool, args),
                    HttpResponse.BodyHandlers.ofString());
            int status = response.statusCode();
            if (status == 429) {
                long retryAfter = response.headers().firstValueAsLong("Retry-After").orElse(1L << attempt);
                Thread.sleep(retryAfter * 1000L);
                continue;
            }
            if (status >= 500) {
                Thread.sleep(1000L * (1L << attempt));
                continue;
            }
            if (status >= 400) {
                JsonNode body = objectMapper.readTree(response.body());
                throw new HiveException(status,
                        body.path("error").path("code").asText("unknown"),
                        body.path("error").path("message").asText(response.body()));
            }
            return objectMapper.readValue(response.body(), Map.class);
        } catch (java.io.IOException | InterruptedException exc) {
            last = exc;
            Thread.sleep(1000L * (1L << attempt));
        }
    }
    throw new HiveException(0, "exhausted_retries", "All retries failed: " + last);
}

Key HTTP codes to handle:

  • 400 — invalid tool name or args.
  • 401 — missing or invalid API key. Rotate via the dashboard; don't retry.
  • 429 — rate-limited. Honor Retry-After; exponential backoff otherwise.
  • 502 / 503 — upstream provider failure. Exponential backoff.

Async with CompletableFuture

For fan-out patterns (daily briefings, concurrent wallet profiles) use sendAsync:

import java.util.concurrent.CompletableFuture;
import java.util.List;

public CompletableFuture<JsonNode> executeAsync(String tool, Map<String, Object> args) throws Exception {
    HttpRequest request = buildRequest(tool, args);
    return httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())
            .thenApply(response -> {
                if (response.statusCode() >= 300) {
                    throw new RuntimeException("Hive call failed: " + response.body());
                }
                try {
                    return objectMapper.readTree(response.body());
                } catch (Exception exc) {
                    throw new RuntimeException(exc);
                }
            });
}

// Fan out 3 concurrent tool calls for a market brief
HiveClient client = new HiveClient(System.getenv("HIVE_API_KEY"));
CompletableFuture<JsonNode> prices = client.executeAsync("get_price", Map.of(
        "ids", "bitcoin,ethereum", "vs_currencies", "usd"));
CompletableFuture<JsonNode> tvl = client.executeAsync("get_protocol_tvl", Map.of());
CompletableFuture<JsonNode> oi = client.executeAsync("get_open_interest", Map.of("exchange", "binance"));

CompletableFuture.allOf(prices, tvl, oi).join();
System.out.println("Brief assembled: " + prices.get() + tvl.get() + oi.get());

Hive bills one credit per tool call regardless of concurrency, so fan-out is the right default for research and reporting agents.


Tool Discovery

Prefer runtime discovery over hardcoded schemas — new tools show up automatically as Hive ships providers:

public List<JsonNode> discover(String search) throws Exception {
    List<JsonNode> items = new java.util.ArrayList<>();
    String cursor = null;
    while (true) {
        StringBuilder url = new StringBuilder(baseUrl).append("/api/v1/tools?limit=200");
        if (cursor != null) url.append("&cursor=").append(cursor);
        if (search != null) url.append("&search=").append(search);
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url.toString()))
                .header("Authorization", "Bearer " + apiKey)
                .GET().build();
        JsonNode page = objectMapper.readTree(
                httpClient.send(request, HttpResponse.BodyHandlers.ofString()).body());
        page.path("data").forEach(items::add);
        JsonNode nextCursor = page.path("meta").path("cursor");
        if (nextCursor.isMissingNode() || nextCursor.isNull()) return items;
        cursor = nextCursor.asText();
    }
}

List<JsonNode> walletTools = client.discover("wallet");

Spring Boot Integration

If you run on Spring, register the client as a singleton bean and inject it into services:

@Configuration
public class HiveConfig {
    @Bean
    public HiveClient hiveClient(@Value("${hive.api.key}") String apiKey) {
        return new HiveClient(apiKey);
    }
}

@Service
public class MarketIntelService {
    private final HiveClient hive;

    public MarketIntelService(HiveClient hive) {
        this.hive = hive;
    }

    public Map<String, Object> briefing() throws Exception {
        return hive.execute("get_price",
                Map.of("ids", "bitcoin,ethereum,solana", "vs_currencies", "usd"));
    }
}

Use Spring's @Retryable or Resilience4j for retry policy instead of hand-rolled loops.


Notes

  • The current REST payload keys are tool and args. Older toolName / arguments examples are legacy.
  • Use GET /api/v1/tools for live schemas and tool discovery; never hardcode definitions.
  • Failed 4xx calls do not consume credits; 5xx server errors are refunded.
  • Every response carries a fetched_at timestamp agents can use to reason about staleness.