EU GPT logo
EU GPT

Public preview — This API is in public preview. Endpoints, schemas, and limits may change before general availability.

API

Your first request

Step-by-step walkthroughs in curl, JavaScript, and Python — and how to read each response.

This guide walks through one complete request end-to-end, in three languages. You will set up the environment, send the request, and parse the response.

Setup#

You need:

  • An EU GPT API key (see Authentication).
  • The key exported as EUGPT_API_KEY so the snippets below pick it up without inlining it.
export EUGPT_API_KEY="eugpt_..."

Non-streaming: ask one question, get one answer#

The simplest possible request. stream: false returns one JSON document; no SSE parsing required.

curl https://chat.eugpt.ai/v1/responses \
  -H "Authorization: Bearer $EUGPT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "auto",
    "input": "Explain the EU AI Act in three short bullets.",
    "stream": false
  }'
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.EUGPT_API_KEY,
  baseURL: "https://chat.eugpt.ai/v1",
});

const response = await client.responses.create({
  model: "auto",
  input: "Explain the EU AI Act in three short bullets.",
  stream: false,
});

console.log(response.output_text);
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["EUGPT_API_KEY"],
    base_url="https://chat.eugpt.ai/v1",
)

response = client.responses.create(
    model="auto",
    input="Explain the EU AI Act in three short bullets.",
    stream=False,
)

print(response.output_text)

The shape of the JSON body is documented in Create a response.

Streaming: render output as it arrives#

For anything user-facing, stream. The first text chunks arrive within a few hundred milliseconds, even when the full response takes a few seconds.

curl -N https://chat.eugpt.ai/v1/responses \
  -H "Authorization: Bearer $EUGPT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "auto",
    "input": "Write a long-form explanation of data sovereignty."
  }'
const stream = await client.responses.create({
  model: "auto",
  input: "Write a long-form explanation of data sovereignty.",
  stream: true,
});

for await (const event of stream) {
  if (event.type === "response.output_text.delta") {
    process.stdout.write(event.delta);
  } else if (event.type === "response.completed") {
    process.stdout.write("\n");
  }
}
stream = client.responses.create(
    model="auto",
    input="Write a long-form explanation of data sovereignty.",
    stream=True,
)

for event in stream:
    if event.type == "response.output_text.delta":
        print(event.delta, end="", flush=True)
    elif event.type == "response.completed":
        print()

Adding a system prompt#

instructions steers tone, format, and persona for this response.

const response = await client.responses.create({
  model: "auto",
  input: "Summarise the GDPR.",
  instructions: "Respond in Dutch. Use exactly five bullet points.",
  stream: false,
});

If you also pass a brand-new conversation_id, the instructions are stored as the conversation’s system message and apply to every subsequent turn.

Continuing the conversation#

Capture the conversation id and pass it on the next call. (The conversation id is returned on every response — for stateless requests it identifies the ephemeral, hidden conversation that was created.)

const first = await client.responses.create({
  model: "auto",
  input: "Plan a sprint to migrate from Chat Completions.",
});
const conversationId = first.conversation_id;

const followUp = await client.responses.create({
  model: "auto",
  conversation_id: conversationId,
  input: "Now expand step 3 into substeps.",
});

Error handling#

Always check for the error envelope. Status codes you should plan for: 400, 401, 403, 429, 5xx. See Errors for retry guidance.

try {
  const response = await client.responses.create({ /* … */ });
  return response.output_text;
} catch (err) {
  if (err.status === 429) {
    // Quota hit. Back off, upgrade plan, or queue.
  } else if (err.status >= 500) {
    // Transient. Retry with exponential backoff.
  } else {
    // Something the user did. Surface to caller.
    throw err;
  }
}

Next steps#

  • Handling streams — parsing without an SDK, custom event handling.
  • Tool use — what to do when the model decides to call web_search.