All examples in this page assume environment variables are available. For convenience, create a .env file in the repository root (you can copy from .env.example) with:
Set TUDELFT_TULIP_BASE_URL to host root only (for example https://api.tulip.tudelft.nl). The Python helper normalizes it to a capability-specific /v1 endpoint automatically.
What these examples assume
The Python snippets on this page assume a local helper file common.py that loads environment variables and exports shared constants.
If you cloned this repository, examples/common.py is already present and the scripts run as shown below.
If you have not cloned the repo and are working with Python, expand the helper snippet below and place common.py next to the example you want to run.
Python run commands use pixi run python ...; dependencies come from pixi.toml.
Bash examples pretty-print JSON using jq, so you may need to install it.
TUDELFT_TULIP_CAPABILITY chooses the path segment (chat, code, embed).
TUDELFT_TULIP_MODEL_ALIAS chooses the deployed model alias.
If you have not cloned the repo and are working with Python, create common.py next to the example
importosfromdotenvimportload_dotenvload_dotenv()# loads .env if presentTUDELFT_TULIP_BASE_URL=os.getenv("TUDELFT_TULIP_BASE_URL","https://api.tulip.tudelft.nl")TUDELFT_TULIP_CAPABILITY=os.getenv("TUDELFT_TULIP_CAPABILITY","chat")TUDELFT_TULIP_API_KEY=os.getenv("TUDELFT_TULIP_API_KEY","DUMMY_KEY")TUDELFT_TULIP_MODEL_ALIAS=os.getenv("TUDELFT_TULIP_MODEL_ALIAS","chat")# Normalize TUDELFT_TULIP_BASE_URL to capability/v1. Docs recommend host root only,# but we also accept URLs that already include capability or capability/v1._base_url=TUDELFT_TULIP_BASE_URL.rstrip("/")if_base_url.endswith("/v1"):TUDELFT_TULIP_BASE_URL=_base_urlelif_base_url.endswith(f"/{TUDELFT_TULIP_CAPABILITY}"):TUDELFT_TULIP_BASE_URL=f"{_base_url}/v1"else:TUDELFT_TULIP_BASE_URL=f"{_base_url}/{TUDELFT_TULIP_CAPABILITY}/v1"
This tutorial covers two endpoints:
/v1/responses
/v1/chat/completions
Quick setup
Use curl-responses-basic.sh / python_responses_basic.py for /v1/responses, and curl-chat-completions.sh / python_chat_completions.py for /v1/chat/completions.
Responses API
Recommended approach
OpenAI recommends /v1/responses for new projects. It supports all capabilities (chat, code, embed) and provides a unified interface for text and non-text outputs.
For more, seeOpenAI Responses API.
#!/bin/bashSCRIPT_DIR="$(cd--"$(dirname--"${BASH_SOURCE[0]}")"&&pwd)"if[-f"${SCRIPT_DIR}/../.env"];thensource"${SCRIPT_DIR}/../.env"ficurl-s--fail--show-error${TUDELFT_TULIP_BASE_URL}/${TUDELFT_TULIP_CAPABILITY}/v1/responses\-H"Content-Type: application/json"\-H"Authorization: Bearer ${TUDELFT_TULIP_API_KEY}"\-d'{ "model": "'"${TUDELFT_TULIP_MODEL_ALIAS}"'", "input": "Tell me a three sentence bedtime story about a unicorn." }'|jq.
fromcommonimport(TUDELFT_TULIP_API_KEY,TUDELFT_TULIP_BASE_URL,TUDELFT_TULIP_MODEL_ALIAS,)fromopenaiimportOpenAIclient=OpenAI(base_url=TUDELFT_TULIP_BASE_URL,api_key=TUDELFT_TULIP_API_KEY)model=TUDELFT_TULIP_MODEL_ALIASresponse=client.responses.create(model=model,input="Tell me a three sentence bedtime story about a unicorn.",)print(response.output_text)
Run:
pixirunpythonexamples/python_responses_basic.py
Success looks like
Bash: curl-responses-basic.sh prints a valid JSON response object from /v1/responses.
Python: python_responses_basic.py prints extracted model text via response.output_text.
Chat Completions
Legacy endpoint (chat/completions only)
/v1/chat/completions is available for chat and code capabilities only. It does not support embeddings. For new projects or to work with all capabilities uniformly, prefer /v1/responses above.
For more, seeOpenAI Chat Completions API.
#!/bin/bashSCRIPT_DIR="$(cd--"$(dirname--"${BASH_SOURCE[0]}")"&&pwd)"if[-f"${SCRIPT_DIR}/../.env"];thensource"${SCRIPT_DIR}/../.env"ficurl-s--fail--show-error${TUDELFT_TULIP_BASE_URL}/${TUDELFT_TULIP_CAPABILITY}/v1/chat/completions\-H"Content-Type: application/json"\-H"Authorization: Bearer ${TUDELFT_TULIP_API_KEY}"\-d'{ "model": "'"${TUDELFT_TULIP_MODEL_ALIAS}"'", "max_tokens": 256, "temperature": 0.2, "messages": [ { "role": "system", "content": "You are a helpful coding assistant for TU Delft." }, { "role": "user", "content": "Write a tiny Python function that prints the TU Delft logo in ASCII." } ] }'|jq.
fromcommonimport(TUDELFT_TULIP_API_KEY,TUDELFT_TULIP_BASE_URL,TUDELFT_TULIP_MODEL_ALIAS,)fromopenaiimportOpenAIclient=OpenAI(base_url=TUDELFT_TULIP_BASE_URL,api_key=TUDELFT_TULIP_API_KEY)model=TUDELFT_TULIP_MODEL_ALIAScompletion=client.chat.completions.create(model=model,messages=[{"role":"developer","content":"You are a helpful coding assistant for TU Delft.",},{"role":"user","content":("Write a tiny Python function that prints the TU Delft logo in ASCII."),},],)print(completion.choices[0].message.content)
Run:
pixirunpythonexamples/python_chat_completions.py
Success looks like
Bash: curl-chat-completions.sh returns valid JSON from /v1/chat/completions.
Python: python_chat_completions.py prints assistant text from completion.choices[0].message.content.
importasynciofromcommonimport(TUDELFT_TULIP_API_KEY,TUDELFT_TULIP_BASE_URL,TUDELFT_TULIP_MODEL_ALIAS,)fromopenaiimportAsyncOpenAIclient=AsyncOpenAI(base_url=TUDELFT_TULIP_BASE_URL,api_key=TUDELFT_TULIP_API_KEY)model=TUDELFT_TULIP_MODEL_ALIASasyncdefmain()->None:response=awaitclient.responses.create(model=model,input="Explain disestablishmentarianism to a smart five year old.")print(response.output_text)asyncio.run(main())
Run:
pixirunpythonexamples/python_responses_async.py
Success looks like
Script finishes normally and prints text output.
No async transport or timeout errors for a basic request.
Streaming chat
Endpoint pattern: Chat completions with stream=True
Warning
Some deployments may not expose OpenAI Responses streaming events yet.
This example uses chat-completions streaming for maximum compatibility.
For more, seeOpenAI Streaming Responses guide.
fromcommonimport(TUDELFT_TULIP_API_KEY,TUDELFT_TULIP_BASE_URL,TUDELFT_TULIP_MODEL_ALIAS,)fromopenaiimportOpenAIclient=OpenAI(base_url=TUDELFT_TULIP_BASE_URL,api_key=TUDELFT_TULIP_API_KEY)model=TUDELFT_TULIP_MODEL_ALIASstream=client.chat.completions.create(model=model,messages=[{"role":"user","content":"Hello TULIP streaming test!"}],stream=True,)forchunkinstream:# Each chunk is a ChatCompletionChunk; content trickles in delta.ifchunk.choicesandchunk.choices[0].deltaandchunk.choices[0].delta.content:print(chunk.choices[0].delta.content,end="",flush=True)print()
Run:
pixirunpythonexamples/python_responses_stream.py
Success looks like
Output appears progressively token-by-token or chunk-by-chunk.
Stream completes with no protocol or parsing errors.