Tutorials & Integrations

Java Integration

Written by , Product docsLast updated

Use Hive from JVM services with Java HttpClient. This guide covers bearer authentication, REST execution, tool discovery, structured error handling, and reusable client code for services that need live crypto prices, wallet data, DeFi analytics, and token security.

Requirements: Java 11+


Dependencies

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

Quick start

java
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
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());

        JsonNode body = mapper.readTree(response.body());
        System.out.println(body.path("data").path("bitcoin").path("usd"));
        System.out.println(body.path("meta").path("fetched_at"));
    }
}

Reusable client

java
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());
        }

        Map<String, Object> body = objectMapper.readValue(response.body(), Map.class);
        if (Boolean.FALSE.equals(body.get("ok"))) {
            Map<String, Object> error = (Map<String, Object>) body.get("error");
            throw new RuntimeException(String.valueOf(error.getOrDefault("message", "Hive execution failed")));
        }
        return body;
    }
}

Discovery

java
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

java
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("alchemy_get_token_balances_by_wallet", Map.of(
    "address", "0x1234...",
    "network", "eth-mainnet"
));

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

System.out.println(market.get("data"));
System.out.println(wallet.get("data"));
System.out.println(prediction.get("data"));

Error handling

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

java
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()));
            }
            JsonNode body = objectMapper.readTree(response.body());
            if (!body.path("ok").asBoolean(true)) {
                throw new HiveException(status,
                        body.path("error").path("code").asText("execution_error"),
                        body.path("error").path("message").asText("Hive execution failed"));
            }
            return objectMapper.convertValue(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.
  • 503 (PROVIDER_UNAVAILABLE): upstream provider failure. Exponential backoff.

Async with CompletableFuture

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

java
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 {
                    JsonNode body = objectMapper.readTree(response.body());
                    if (!body.path("ok").asBoolean(true)) {
                        throw new RuntimeException(body.path("error").path("message").asText("Hive execution failed"));
                    }
                    return 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("protocol", "aave"));
CompletableFuture<JsonNode> oi = client.executeAsync("get_open_interest",
        Map.of("exchange", "binance", "symbol", "BTC/USDT:USDT"));

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

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 so your app can inspect current Hive tool definitions as providers change:

java
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:

java
@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.
  • Authenticated execution and discovery requests can count against quota once accepted by the backend. Cache discovery responses and validate inputs before sending requests.
  • Every execution includes a fetched_at timestamp agents can use to reason about staleness.