curl https://compute.prentis.ai/v1/messages \
-H "x-api-key: $PRENTIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4.1-flash",
"system": "You are a concise assistant.",
"messages": [
{"role": "user", "content": "Summarise the CAP theorem in two sentences."}
],
"max_tokens": 200,
"temperature": 0.7
}'import os
import anthropic
# The SDK appends /v1/messages itself, so it takes the origin.
client = anthropic.Anthropic(base_url="https://compute.prentis.ai", api_key=os.environ["PRENTIS_API_KEY"])
msg = client.messages.create(
model="deepseek-v4.1-flash",
system="You are a concise assistant.",
messages=[{"role": "user", "content": "Summarise the CAP theorem in two sentences."}],
max_tokens=200,
)
print(msg.content[0].text)import Anthropic from "@anthropic-ai/sdk";
// The SDK appends /v1/messages itself, so it takes the origin.
const client = new Anthropic({
baseURL: "https://compute.prentis.ai",
apiKey: process.env.PRENTIS_API_KEY,
});
const msg = await client.messages.create({
model: "deepseek-v4.1-flash",
system: "You are a concise assistant.",
messages: [{ role: "user", content: "Summarise the CAP theorem in two sentences." }],
max_tokens: 200,
});
console.log(msg.content[0]?.type === "text" ? msg.content[0].text : "");const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
messages: [{content: '<string>'}],
system: '<string>',
max_tokens: 2,
stream: false,
stop_sequences: ['<string>'],
temperature: 1,
top_p: 0.5,
top_k: 123,
tools: [{}],
tool_choice: {},
metadata: {user_id: '<string>'},
thinking: {},
output_config: {},
raw_output: {}
})
};
fetch('https://compute.prentis.ai/v1/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://compute.prentis.ai/v1/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'messages' => [
[
'content' => '<string>'
]
],
'system' => '<string>',
'max_tokens' => 2,
'stream' => false,
'stop_sequences' => [
'<string>'
],
'temperature' => 1,
'top_p' => 0.5,
'top_k' => 123,
'tools' => [
[
]
],
'tool_choice' => [
],
'metadata' => [
'user_id' => '<string>'
],
'thinking' => [
],
'output_config' => [
],
'raw_output' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://compute.prentis.ai/v1/messages"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"messages\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"system\": \"<string>\",\n \"max_tokens\": 2,\n \"stream\": false,\n \"stop_sequences\": [\n \"<string>\"\n ],\n \"temperature\": 1,\n \"top_p\": 0.5,\n \"top_k\": 123,\n \"tools\": [\n {}\n ],\n \"tool_choice\": {},\n \"metadata\": {\n \"user_id\": \"<string>\"\n },\n \"thinking\": {},\n \"output_config\": {},\n \"raw_output\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://compute.prentis.ai/v1/messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"messages\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"system\": \"<string>\",\n \"max_tokens\": 2,\n \"stream\": false,\n \"stop_sequences\": [\n \"<string>\"\n ],\n \"temperature\": 1,\n \"top_p\": 0.5,\n \"top_k\": 123,\n \"tools\": [\n {}\n ],\n \"tool_choice\": {},\n \"metadata\": {\n \"user_id\": \"<string>\"\n },\n \"thinking\": {},\n \"output_config\": {},\n \"raw_output\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://compute.prentis.ai/v1/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"messages\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"system\": \"<string>\",\n \"max_tokens\": 2,\n \"stream\": false,\n \"stop_sequences\": [\n \"<string>\"\n ],\n \"temperature\": 1,\n \"top_p\": 0.5,\n \"top_k\": 123,\n \"tools\": [\n {}\n ],\n \"tool_choice\": {},\n \"metadata\": {\n \"user_id\": \"<string>\"\n },\n \"thinking\": {},\n \"output_config\": {},\n \"raw_output\": {}\n}"
response = http.request(request)
puts response.read_body{
"id": "msg_01K5S8QW6ATE",
"type": "message",
"role": "assistant",
"model": "deepseek-v4.1-flash",
"content": [
{
"type": "text",
"text": "A distributed store can hold at most two of consistency, availability and partition tolerance at once. Because partitions do happen in practice, the real choice is between answering with stale data and not answering at all."
}
],
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 28,
"output_tokens": 47,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0
}
}{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "<string>"
},
"code": "<string>",
"param": "<string>",
"request_id": "<string>"
}{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "<string>"
},
"code": "<string>",
"param": "<string>",
"request_id": "<string>"
}Messages
Anthropic-compatible Messages endpoint. Anthropic SDKs and Claude Code work by changing base_url alone, and x-api-key is accepted alongside Authorization: Bearer. Pass a Prentis model name — there is no claude-* aliasing.
curl https://compute.prentis.ai/v1/messages \
-H "x-api-key: $PRENTIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4.1-flash",
"system": "You are a concise assistant.",
"messages": [
{"role": "user", "content": "Summarise the CAP theorem in two sentences."}
],
"max_tokens": 200,
"temperature": 0.7
}'import os
import anthropic
# The SDK appends /v1/messages itself, so it takes the origin.
client = anthropic.Anthropic(base_url="https://compute.prentis.ai", api_key=os.environ["PRENTIS_API_KEY"])
msg = client.messages.create(
model="deepseek-v4.1-flash",
system="You are a concise assistant.",
messages=[{"role": "user", "content": "Summarise the CAP theorem in two sentences."}],
max_tokens=200,
)
print(msg.content[0].text)import Anthropic from "@anthropic-ai/sdk";
// The SDK appends /v1/messages itself, so it takes the origin.
const client = new Anthropic({
baseURL: "https://compute.prentis.ai",
apiKey: process.env.PRENTIS_API_KEY,
});
const msg = await client.messages.create({
model: "deepseek-v4.1-flash",
system: "You are a concise assistant.",
messages: [{ role: "user", content: "Summarise the CAP theorem in two sentences." }],
max_tokens: 200,
});
console.log(msg.content[0]?.type === "text" ? msg.content[0].text : "");const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
messages: [{content: '<string>'}],
system: '<string>',
max_tokens: 2,
stream: false,
stop_sequences: ['<string>'],
temperature: 1,
top_p: 0.5,
top_k: 123,
tools: [{}],
tool_choice: {},
metadata: {user_id: '<string>'},
thinking: {},
output_config: {},
raw_output: {}
})
};
fetch('https://compute.prentis.ai/v1/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://compute.prentis.ai/v1/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'messages' => [
[
'content' => '<string>'
]
],
'system' => '<string>',
'max_tokens' => 2,
'stream' => false,
'stop_sequences' => [
'<string>'
],
'temperature' => 1,
'top_p' => 0.5,
'top_k' => 123,
'tools' => [
[
]
],
'tool_choice' => [
],
'metadata' => [
'user_id' => '<string>'
],
'thinking' => [
],
'output_config' => [
],
'raw_output' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://compute.prentis.ai/v1/messages"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"messages\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"system\": \"<string>\",\n \"max_tokens\": 2,\n \"stream\": false,\n \"stop_sequences\": [\n \"<string>\"\n ],\n \"temperature\": 1,\n \"top_p\": 0.5,\n \"top_k\": 123,\n \"tools\": [\n {}\n ],\n \"tool_choice\": {},\n \"metadata\": {\n \"user_id\": \"<string>\"\n },\n \"thinking\": {},\n \"output_config\": {},\n \"raw_output\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://compute.prentis.ai/v1/messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"messages\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"system\": \"<string>\",\n \"max_tokens\": 2,\n \"stream\": false,\n \"stop_sequences\": [\n \"<string>\"\n ],\n \"temperature\": 1,\n \"top_p\": 0.5,\n \"top_k\": 123,\n \"tools\": [\n {}\n ],\n \"tool_choice\": {},\n \"metadata\": {\n \"user_id\": \"<string>\"\n },\n \"thinking\": {},\n \"output_config\": {},\n \"raw_output\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://compute.prentis.ai/v1/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"messages\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"system\": \"<string>\",\n \"max_tokens\": 2,\n \"stream\": false,\n \"stop_sequences\": [\n \"<string>\"\n ],\n \"temperature\": 1,\n \"top_p\": 0.5,\n \"top_k\": 123,\n \"tools\": [\n {}\n ],\n \"tool_choice\": {},\n \"metadata\": {\n \"user_id\": \"<string>\"\n },\n \"thinking\": {},\n \"output_config\": {},\n \"raw_output\": {}\n}"
response = http.request(request)
puts response.read_body{
"id": "msg_01K5S8QW6ATE",
"type": "message",
"role": "assistant",
"model": "deepseek-v4.1-flash",
"content": [
{
"type": "text",
"text": "A distributed store can hold at most two of consistency, availability and partition tolerance at once. Because partitions do happen in practice, the real choice is between answering with stale data and not answering at all."
}
],
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 28,
"output_tokens": 47,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0
}
}{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "<string>"
},
"code": "<string>",
"param": "<string>",
"request_id": "<string>"
}{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "<string>"
},
"code": "<string>",
"param": "<string>",
"request_id": "<string>"
}base_url alone.
Two differences from Anthropic’s own API
Model names stay ours. There is noclaude-* aliasing — pass a model from
GET /models. See
Models and resource names.
max_tokens is optional. Anthropic’s API requires it; here, omitting it falls back to
the model’s own default rather than failing the call.
Authentication
Both headers work, and they name the same key:x-api-key: $PRENTIS_API_KEY
# or
Authorization: Bearer $PRENTIS_API_KEY
/v1/messages themselves, so construct them with the origin:
client = anthropic.Anthropic(
base_url="https://compute.prentis.ai",
api_key=os.environ["PRENTIS_API_KEY"],
)
Authorizations
Authorization: Bearer <your API key>. On /v1/messages, the Anthropic-style x-api-key: <your API key> header is accepted instead.
Body
Which model answers the call. A bare slug for platform models (deepseek-v4.1-flash), or a full resource name for something your account owns (accounts/{account}/models/{model}, or a deployment). Never an upstream vendor's own name.
The conversation so far, oldest first. Only user and assistant turns -- the system prompt travels in its own system field. Content is a string, or a list of text / image / tool_use / tool_result blocks.
1Show child attributes
Show child attributes
Instructions that sit outside the conversation. Counted as input tokens like any other prompt text.
Ceiling on how many tokens may be generated. Anthropic's own API requires this; here it is optional and falls back to the model's default rather than failing the call.
x >= 1Return the answer as server-sent events as it is generated, instead of one response at the end. The last data event carries the usage numbers either way.
Up to 4 strings that end generation as soon as the model produces one. The matched string is not included in the output.
4How much randomness to allow when picking each token. Lower is more repeatable, higher is more varied.
0 <= x <= 2Nucleus sampling: only consider the most likely tokens up to this share of the probability mass. Tune this or temperature, not both.
0 <= x <= 1Accepted so Anthropic clients do not break, then dropped: it is not passed to the model.
Tool definitions in Anthropic's shape ({name, description, input_schema}). Server-side built-in tools are rejected by name.
Whether the model may, must, or must not call a tool: auto, any, none, or one named tool.
Free-form metadata about the call. metadata.user_id is the equivalent of the user field on the OpenAI-shaped endpoints.
Show child attributes
Show child attributes
Extended thinking configuration.
Vendor-specific output configuration.
Not supported. Sending it returns INVALID_REQUEST.
Vendor-specific raw output configuration.
Not supported. Sending it returns INVALID_REQUEST.
Response
OK. With stream: true the same call answers text/event-stream instead, one chunk per event, terminated by data: [DONE]; the last data event carries usage whether or not you asked for it.
"message""assistant"Show child attributes
Show child attributes
Show child attributes
Show child attributes
end_turn, max_tokens, stop_sequence, tool_use, refusal, null