Messages API
The Messages API is Claude’s core request/response endpoint: you send a list of Messages (each a list of ContentBlocks — text, images, tool results) and receive the assistant’s reply. This page covers building MessageRequests: multi-turn conversations, system prompts, images, and the advanced sampling parameters. For sending the request see basics; for tools and structured outputs see Tool calling and Structured outputs.
Basic text conversation
//> using dep com.softwaremill.sttp.ai::claude:0.11.0
import sttp.ai.claude.models.{ClaudeModel, ContentBlock, Message}
import sttp.ai.claude.requests.MessageRequest
val messages = List(
Message.user(List(ContentBlock.text("What is the capital of France?"))),
Message.assistant(List(ContentBlock.text("The capital of France is Paris."))),
Message.user(List(ContentBlock.text("What about Italy?")))
)
val request = MessageRequest.simple(
model = ClaudeModel.ClaudeSonnet5.value,
messages = messages,
maxTokens = 1000
)
System messages
Unlike OpenAI, Claude uses a separate system parameter instead of system role messages:
//> using dep com.softwaremill.sttp.ai::claude:0.11.0
import sttp.ai.claude.models.{ClaudeModel, ContentBlock, Message}
import sttp.ai.claude.requests.MessageRequest
val request = MessageRequest.withSystem(
model = ClaudeModel.ClaudeSonnet5.value,
system = "You are a helpful assistant that always responds in French.",
messages = List(Message.user(List(ContentBlock.text("Hello!")))),
maxTokens = 1000
)
Image support
//> using dep com.softwaremill.sttp.ai::claude:0.11.0
import java.util.Base64
import java.nio.file.{Files, Paths}
import sttp.ai.claude.models.{ClaudeModel, ContentBlock, Message}
import sttp.ai.claude.requests.MessageRequest
// Read and encode image
val imageBytes = Files.readAllBytes(Paths.get("image.jpg"))
val base64Image = Base64.getEncoder.encodeToString(imageBytes)
val messages = List(
Message.user(List(
ContentBlock.text("What do you see in this image?"),
ContentBlock.image(
mediaType = "image/jpeg",
data = base64Image
)
))
)
val request = MessageRequest.simple(
model = ClaudeModel.ClaudeSonnet5.value,
messages = messages,
maxTokens = 1000
)
Advanced parameters
//> using dep com.softwaremill.sttp.ai::claude:0.11.0
import sttp.ai.claude.models.{CacheControl, ClaudeModel, ContentBlock, Message}
import sttp.ai.claude.requests.MessageRequest
val messages = List(Message.user(List(ContentBlock.text("Hello!"))))
val request = MessageRequest(
model = ClaudeModel.ClaudeSonnet5.value,
messages = messages,
maxTokens = 4000,
temperature = Some(0.7), // Creativity (0.0 - 1.0)
topP = Some(0.9), // Nucleus sampling
topK = Some(40), // Top-k sampling
stopSequences = Some(List("\n\n")), // Stop generation at sequences
system = Some("Be concise and helpful."),
tools = None, // See tool-calling.md
cacheControl = Some(CacheControl.Ephemeral()) // Optional cache control
)
Usage and cache accounting
Regarding caching and usage, note the formula used to calculate the number of input tokens consumed by the model (relevant for billing and context window management):
case class Usage(
inputTokens: Int,
outputTokens: Int,
cacheReadInputTokens: Option[Int] = None,
cacheCreationInputTokens: Option[Int] = None
) {
def totalInputTokens: Int = inputTokens + cacheReadInputTokens.getOrElse(0) + cacheCreationInputTokens.getOrElse(0)
def totalTokens: Int = totalInputTokens + outputTokens
}