← Blog

Claude API Java SDK Integration Tutorial

2026-10-25 · 5 min read · SubToAPI Team

Anthropic does not publish an official Java SDK for Claude. If you're searching for one, the short answer is: you have three practical paths — use a community-maintained Java client, call the REST API directly with Java's built-in HttpClient, or go through a gateway like SubToAPI that gives you a stable HTTPS endpoint you can hit from any language, including Java, without writing your own retry and auth plumbing.

This tutorial covers all three so you can pick the right one for your project, then walks through a working integration using plain Java — no extra dependencies required — plus how tool use and streaming fit into that setup.

Why there's no official Java SDK

Anthropic maintains official SDKs for Python and TypeScript/JavaScript. Java, Go, and most other languages are left to the community or to direct HTTP calls. Since Claude's API is a standard JSON-over-HTTPS REST interface, this isn't a blocker — it just means you're responsible for building the request/response plumbing yourself, or relying on a third-party library that wraps it.

Two realistic options if you don't want to roll your own client:

For most teams, calling the REST API directly with java.net.http.HttpClient (built into Java 11+) is the most reliable choice — zero extra dependencies, full control, and no risk of an abandoned wrapper breaking your build.

Setting up a Java HTTP client for Claude

Here's a minimal, dependency-free Java class that sends a message request:

import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

public class ClaudeClient {
    private static final String API_URL = "https://api.anthropic.com/v1/messages";
    private final String apiKey;
    private final HttpClient client = HttpClient.newHttpClient();

    public ClaudeClient(String apiKey) {
        this.apiKey = apiKey;
    }

    public String sendMessage(String model, String userMessage) throws Exception {
        String body = """
            {
              "model": "%s",
              "max_tokens": 1024,
              "messages": [{"role": "user", "content": "%s"}]
            }
            """.formatted(model, userMessage);

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(API_URL))
            .header("x-api-key", apiKey)
            .header("anthropic-version", "2023-06-01")
            .header("content-type", "application/json")
            .POST(BodyPublishers.ofString(body))
            .build();

        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        return response.body();
    }
}

This is enough to get a working integration, but in production you'll quickly need to handle rate limit retries, token usage tracking per user, and multiple application keys if more than one service calls Claude. That's the point where writing your own Java client starts costing more time than it saves.

A simpler path: a single REST contract for your whole stack

If your Java backend is one of several services (a mobile API, an internal tool, a Slack bot) that all need Claude access, managing separate Anthropic credentials and retry logic in each one gets messy fast. SubToAPI sits in front of your Claude access and exposes it as a standard HTTPS API with its own sub_live_... application keys, so your Java code — and every other service in your stack — talks to one consistent endpoint.

Because it's plain REST, the same HttpClient pattern above works unchanged — you just point it at a different host and auth header:

curl https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Summarize this changelog"}]
  }'

Drop that into the Java client above by swapping the URL and header, and you get per-application keys, usage metadata per request, and team seats in a dashboard — without building any of that yourself. The quickstart and messages endpoint docs cover the full request shape.

Handling streaming and tool use in Java

Claude's streaming responses use server-sent events (SSE). Java's HttpClient doesn't parse SSE natively, so you either read the response body line-by-line and split on data: prefixes, or use a reactive HTTP client (like Spring WebClient or OkHttp with an SSE extension) that handles the framing for you.

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create(API_URL))
    .header("x-api-key", apiKey)
    .header("anthropic-version", "2023-06-01")
    .POST(BodyPublishers.ofString(streamingBody))
    .build();

client.sendAsync(request, HttpResponse.BodyHandlers.ofLines())
    .thenAccept(response -> response.body()
        .filter(line -> line.startsWith("data: "))
        .forEach(line -> System.out.println(line.substring(6))));

If you're using SubToAPI, streaming works the same way against its endpoint — see the streaming docs for the exact event format and how to parse content_block_delta chunks.

Tool use follows the same request/response contract: you define tool schemas in the request, Claude returns a tool_use block, your Java code executes the function, and you send the result back in a follow-up message. This works identically whether you call Anthropic directly or through SubToAPI's tools endpoint — the JSON shape doesn't change, only the host and auth header do.

Choosing your approach

Whichever path you pick, the underlying contract is the same JSON API, so switching between direct Anthropic calls and a gateway later is mostly a config change, not a rewrite.

questions

Is there an official Claude Java SDK? No. Anthropic officially supports Python and TypeScript/JavaScript. Java developers use community SDKs, framework integrations like LangChain4j, or direct HTTP calls.

Can I call Claude from Java without any SDK? Yes. Claude's API is standard REST over HTTPS, so Java's built-in java.net.http.HttpClient (Java 11+) is enough to send requests and parse JSON responses with no extra dependencies.

How do I handle streaming responses in Java? Parse the server-sent events stream line by line, filtering for data: prefixes, or use a reactive client like Spring WebClient that handles SSE framing automatically. See the streaming docs for the event format.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →