Tutorials & Integrations
Java Integration
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
<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 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
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
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("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:
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:
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:
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
toolandargs. OldertoolName/argumentsexamples are legacy. - Use
GET /api/v1/toolsfor 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_attimestamp agents can use to reason about staleness.
Related
- API Integration - REST endpoint and request envelope
- Response Formats - parse execution metadata and structured errors
- Rate Limits - cache discovery and back off on throttles
- SDK Overview - compare Java REST with other integration paths