Claude API basics
This module provides native support for Anthropic’s Claude API within the sttp-ai library. Unlike OpenAI compatibility layers, this provides direct access to Claude’s unique features and API structure.
Claude features
✅ Messages API — complete
/v1/messagesimplementation; see Messages API✅ ContentBlock structure — rich message content blocks (text, images); see Messages API
✅ Streaming — server-sent events streaming for fs2, ZIO, Akka, Pekko, and Ox
✅ Tool calling — native Claude tools, custom and predefined
✅ Structured outputs — beta JSON-schema validation (Claude 4.1+ models)
✅ Models API — list available models via
/v1/models✅ Error handling — Claude-specific exception hierarchy
✅ Agent loop — autonomous tool-calling agents via
ClaudeAgent✅ Proper authentication —
x-api-keyandanthropic-versionheaders, handled automatically✅ Cross-platform — Scala 2.13 and Scala 3
Sync and async clients
ClaudeSyncClient— high-level and blocking: methods return the response directly and throw aClaudeExceptionsubclass on error. The recommended default, used in most examples in these docs. Create it withClaudeSyncClient.fromEnv(readsANTHROPIC_API_KEY) orClaudeSyncClient(config); callclose()when done.ClaudeClient— returns raw sttp-client4Requests and parses responses asEither[ClaudeException, A]. Pair it with the sttp backend of your choice (cats-effect, ZIO, Akka/Pekko, Ox).
Basic usage
//> using dep com.softwaremill.sttp.ai::claude:0.11.0
import sttp.ai.claude.ClaudeSyncClient
import sttp.ai.claude.models.{ClaudeModel, ContentBlock, Message}
import sttp.ai.claude.requests.MessageRequest
object Main:
def main(args: Array[String]): Unit =
val claude = ClaudeSyncClient.fromEnv // reads ANTHROPIC_API_KEY
try {
val request = MessageRequest.simple(
model = ClaudeModel.ClaudeHaiku4_5.value,
messages = List(Message.user("Hello Claude! What's the weather like today?")),
maxTokens = 500
)
// Throws a ClaudeException subclass on error
val response = claude.createMessage(request)
response.content.foreach {
case ContentBlock.Text(text, _, _) => println(text)
case _ => () // other content block types
}
println(s"Usage: ${response.usage}")
} finally claude.close()
Async usage
For non-blocking code, use ClaudeClient with an sttp backend of your choice:
//> using dep com.softwaremill.sttp.ai::claude:0.11.0
import sttp.ai.claude.*
import sttp.ai.claude.config.ClaudeConfig
import sttp.ai.claude.models.{ClaudeModel, ContentBlock, Message}
import sttp.ai.claude.requests.MessageRequest
import sttp.client4.*
object Main:
def main(args: Array[String]): Unit =
// Create an instance of ClaudeClient using your Anthropic API key
// Set ANTHROPIC_API_KEY environment variable or pass it directly
val config = ClaudeConfig.fromEnv // reads ANTHROPIC_API_KEY
val backend: SyncBackend = DefaultSyncBackend()
val client = ClaudeClient(config)
// Create a simple message
val messages = List(
Message.user(List(ContentBlock.text("Hello Claude! What's the weather like today?")))
)
val request = MessageRequest.simple(
model = ClaudeModel.ClaudeHaiku4_5.value, // Fast, cost-effective model
messages = messages,
maxTokens = 500
)
// Send the request (returns Either[ClaudeException, MessageResponse])
val response = client.createMessage(request).send(backend)
response.body match {
case Right(messageResponse) =>
messageResponse.content.foreach {
case ContentBlock.Text(text, _, _) => println(text)
case _ => // Handle other content types if needed
}
println(s"Usage: ${messageResponse.usage}")
case Left(error) =>
println(s"Claude API Error: ${error.getMessage}")
}
backend.close()
The example above uses the synchronous sttp backend for brevity, but ClaudeClient works with any sttp4 backend — cats-effect, ZIO, Akka/Pekko, Ox, etc. — by swapping the backend and calling .send(backend) in the corresponding effect.
Key differences from OpenAI:
Uses
ContentBlockinstead of simple strings for rich content (text, images)Separate system parameter instead of system role messages
Different authentication headers (
x-api-key+anthropic-version)Native Claude model names (e.g.,
claude-haiku-4-5-20251001)
Claude configuration
case class ClaudeConfig(
apiKey: String, // Your Anthropic API key
anthropicVersion: String = "2023-06-01", // API version header
baseUrl: Uri = "https://api.anthropic.com", // API base URL
timeout: Duration = 10.minutes, // Request timeout
maxRetries: Int = 3, // Max retry attempts, honored by ClaudeSyncClient
organization: Option[String] = None // Optional organization ID
)
Environment Variables:
ANTHROPIC_API_KEY- Your API key (required)ANTHROPIC_VERSION- API version (optional, defaults to “2023-06-01”)ANTHROPIC_BASE_URL- Custom base URL (optional)
Next steps: see Messages API for conversations, images, and advanced parameters, Tool calling and Structured outputs for advanced request features, Streaming for SSE support, and Models and error handling for the models API and exception hierarchy.