curl https://compute.prentis.ai/v1/responses \
-H "Authorization: Bearer $PRENTIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4.1-flash",
"instructions": "You are a concise assistant.",
"input": "Summarise the CAP theorem in two sentences.",
"max_output_tokens": 200,
"store": false
}'import os
from openai import OpenAI
client = OpenAI(base_url="https://compute.prentis.ai/v1", api_key=os.environ["PRENTIS_API_KEY"])
resp = client.responses.create(
model="deepseek-v4.1-flash",
instructions="You are a concise assistant.",
input="Summarise the CAP theorem in two sentences.",
max_output_tokens=200,
store=False,
)
print(resp.output_text)import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://compute.prentis.ai/v1", apiKey: process.env.PRENTIS_API_KEY });
const resp = await client.responses.create({
model: "deepseek-v4.1-flash",
instructions: "You are a concise assistant.",
input: "Summarise the CAP theorem in two sentences.",
max_output_tokens: 200,
store: false,
});
console.log(resp.output_text);const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
input: '<string>',
store: true,
instructions: '<string>',
max_output_tokens: 2,
temperature: 1,
top_p: 0.5,
stream: false,
tools: [{}],
tool_choice: '<string>',
reasoning: {},
previous_response_id: '<string>'
})
};
fetch('https://compute.prentis.ai/v1/responses', 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/responses",
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>',
'input' => '<string>',
'store' => true,
'instructions' => '<string>',
'max_output_tokens' => 2,
'temperature' => 1,
'top_p' => 0.5,
'stream' => false,
'tools' => [
[
]
],
'tool_choice' => '<string>',
'reasoning' => [
],
'previous_response_id' => '<string>'
]),
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/responses"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"input\": \"<string>\",\n \"store\": true,\n \"instructions\": \"<string>\",\n \"max_output_tokens\": 2,\n \"temperature\": 1,\n \"top_p\": 0.5,\n \"stream\": false,\n \"tools\": [\n {}\n ],\n \"tool_choice\": \"<string>\",\n \"reasoning\": {},\n \"previous_response_id\": \"<string>\"\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/responses")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"input\": \"<string>\",\n \"store\": true,\n \"instructions\": \"<string>\",\n \"max_output_tokens\": 2,\n \"temperature\": 1,\n \"top_p\": 0.5,\n \"stream\": false,\n \"tools\": [\n {}\n ],\n \"tool_choice\": \"<string>\",\n \"reasoning\": {},\n \"previous_response_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://compute.prentis.ai/v1/responses")
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 \"input\": \"<string>\",\n \"store\": true,\n \"instructions\": \"<string>\",\n \"max_output_tokens\": 2,\n \"temperature\": 1,\n \"top_p\": 0.5,\n \"stream\": false,\n \"tools\": [\n {}\n ],\n \"tool_choice\": \"<string>\",\n \"reasoning\": {},\n \"previous_response_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "resp_01K5S8RB2NQX",
"object": "response",
"status": "completed",
"model": "deepseek-v4.1-flash",
"output": [
{
"id": "msg_01K5S8RB2NQX",
"type": "message",
"role": "assistant",
"status": "completed",
"content": [
{
"type": "output_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."
}
]
}
],
"usage": {
"input_tokens": 28,
"output_tokens": 47,
"total_tokens": 75
},
"store": false
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}Responses
OpenAI Responses-compatible endpoint, stateless. Codex and other Responses clients work by changing base_url alone. Every call must send store false and carry the full conversation in input: nothing is kept to continue from, so previous_response_id and retrieving a response later are not offered.
curl https://compute.prentis.ai/v1/responses \
-H "Authorization: Bearer $PRENTIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4.1-flash",
"instructions": "You are a concise assistant.",
"input": "Summarise the CAP theorem in two sentences.",
"max_output_tokens": 200,
"store": false
}'import os
from openai import OpenAI
client = OpenAI(base_url="https://compute.prentis.ai/v1", api_key=os.environ["PRENTIS_API_KEY"])
resp = client.responses.create(
model="deepseek-v4.1-flash",
instructions="You are a concise assistant.",
input="Summarise the CAP theorem in two sentences.",
max_output_tokens=200,
store=False,
)
print(resp.output_text)import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://compute.prentis.ai/v1", apiKey: process.env.PRENTIS_API_KEY });
const resp = await client.responses.create({
model: "deepseek-v4.1-flash",
instructions: "You are a concise assistant.",
input: "Summarise the CAP theorem in two sentences.",
max_output_tokens: 200,
store: false,
});
console.log(resp.output_text);const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
input: '<string>',
store: true,
instructions: '<string>',
max_output_tokens: 2,
temperature: 1,
top_p: 0.5,
stream: false,
tools: [{}],
tool_choice: '<string>',
reasoning: {},
previous_response_id: '<string>'
})
};
fetch('https://compute.prentis.ai/v1/responses', 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/responses",
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>',
'input' => '<string>',
'store' => true,
'instructions' => '<string>',
'max_output_tokens' => 2,
'temperature' => 1,
'top_p' => 0.5,
'stream' => false,
'tools' => [
[
]
],
'tool_choice' => '<string>',
'reasoning' => [
],
'previous_response_id' => '<string>'
]),
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/responses"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"input\": \"<string>\",\n \"store\": true,\n \"instructions\": \"<string>\",\n \"max_output_tokens\": 2,\n \"temperature\": 1,\n \"top_p\": 0.5,\n \"stream\": false,\n \"tools\": [\n {}\n ],\n \"tool_choice\": \"<string>\",\n \"reasoning\": {},\n \"previous_response_id\": \"<string>\"\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/responses")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"input\": \"<string>\",\n \"store\": true,\n \"instructions\": \"<string>\",\n \"max_output_tokens\": 2,\n \"temperature\": 1,\n \"top_p\": 0.5,\n \"stream\": false,\n \"tools\": [\n {}\n ],\n \"tool_choice\": \"<string>\",\n \"reasoning\": {},\n \"previous_response_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://compute.prentis.ai/v1/responses")
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 \"input\": \"<string>\",\n \"store\": true,\n \"instructions\": \"<string>\",\n \"max_output_tokens\": 2,\n \"temperature\": 1,\n \"top_p\": 0.5,\n \"stream\": false,\n \"tools\": [\n {}\n ],\n \"tool_choice\": \"<string>\",\n \"reasoning\": {},\n \"previous_response_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "resp_01K5S8RB2NQX",
"object": "response",
"status": "completed",
"model": "deepseek-v4.1-flash",
"output": [
{
"id": "msg_01K5S8RB2NQX",
"type": "message",
"role": "assistant",
"status": "completed",
"content": [
{
"type": "output_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."
}
]
}
],
"usage": {
"input_tokens": 28,
"output_tokens": 47,
"total_tokens": 75
},
"store": false
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_API_KEY",
"param": "<string>"
}
}base_url alone.
Stateless, on purpose
The real Responses API can store a response and continue from it later. This one keeps nothing, and says so instead of pretending:storemust befalse. Leaving it out meanstrueon OpenAI’s API, so a call without it is rejected rather than quietly not stored.previous_response_idis rejected. Send the whole conversation ininputon every call — earlierfunction_callandfunction_call_outputitems included.- There is no
GETorDELETE /responses/{id}.
Tools
Only{"type": "function", ...} tools reach the model. Tools of any other type — hosted
tools, MCP servers, namespaced groups — are dropped from the list rather than failing the
call, so the model never learns they exist and cannot call them.
Streaming
stream: true returns Responses events, ending at response.completed, which carries the
usage. There is no [DONE] sentinel.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, oldest first: a string, or a list of message, function_call and function_call_output items. Send all of it on every call.
Must be false. This endpoint keeps nothing to retrieve later, so a call that leaves store out or sets it to true is rejected rather than quietly not stored.
Instructions that sit outside the conversation, sent to the model as a system message. Counted as input tokens.
Ceiling on how many tokens may be generated. Omit it to use the model's own default.
x >= 1How 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 <= 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.
Function definitions in the Responses shape ({type: "function", name, description, parameters}). Tools of any other type are dropped from the list, so the model never learns they exist.
Whether the model may, must, or must not call a tool: auto, none, required, or {type: "function", name}.
Ask for the model's reasoning. effort is low, medium or high (minimal counts as low); an object without effort asks for medium. Only models that reason accept it.
Not supported: send the whole conversation in input instead.
Not supported. Sending it returns INVALID_REQUEST.
Response
OK. With stream: true the same call answers text/event-stream instead, as Responses events: response.created, the output item and delta events, and response.completed, which carries usage and ends the stream. There is no [DONE] line. A failure part-way through adds an error event before the stream closes.
"response"completed, incomplete Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes