TL;DR
With the OpenAI API you can add a working chat feature to an app in under 50 lines of code. The backend holds the API key and the conversation history; the web or mobile client only talks to your backend. Streaming is optional, but it makes the app feel much faster.
What we're building
A chat endpoint for a web or mobile app. The user types a message, your backend sends it to the OpenAI API together with the conversation so far, and returns the reply. The API key stays on the server: never ship it inside a mobile app or a frontend bundle, where anyone can extract it.
Setup: Python (Django or Flask)
pip install openai python-decouple
# .env
OPENAI_API_KEY=sk-...
from openai import OpenAI
from decouple import config
client = OpenAI(api_key=config('OPENAI_API_KEY'))
def chat(messages: list) -> str:
"""
messages format:
[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"},
{"role": "assistant", "content": "Hi! How can I help?"},
{"role": "user", "content": "Tell me about Tunisia"}
]
"""
response = client.chat.completions.create(
model="gpt-4o-mini", # Low cost, good enough for most chat use cases
messages=messages,
max_tokens=500,
temperature=0.7
)
return response.choices[0].message.content
A Django API endpoint
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
import json
conversation_history = {} # Use Redis in production!
@csrf_exempt
def chat_view(request):
if request.method != 'POST':
return JsonResponse({'error': 'POST only'}, status=405)
data = json.loads(request.body)
session_id = data.get('session_id', 'default')
user_message = data.get('message', '')
# Get or create conversation history
if session_id not in conversation_history:
conversation_history[session_id] = [
{"role": "system", "content": "You are a helpful assistant for a Tunisian software agency."}
]
# Add user message
conversation_history[session_id].append({
"role": "user", "content": user_message
})
# Get AI response
reply = chat(conversation_history[session_id])
# Add to history
conversation_history[session_id].append({
"role": "assistant", "content": reply
})
return JsonResponse({'reply': reply})
Streaming the response
from django.http import StreamingHttpResponse
def stream_chat(request):
user_message = request.GET.get('message', '')
def generate():
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": user_message}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
yield f"data: {chunk.choices[0].delta.content}\n\n"
yield "data: [DONE]\n\n"
return StreamingHttpResponse(
generate(),
content_type='text/event-stream'
)
GPT-4o-mini costs about $0.15 per million input tokens and $0.60 per million output tokens. A typical chat message is 50 to 100 tokens, but the whole history is sent again on every turn, so long conversations cost more. For most small apps the bill still stays at a few dollars a month.
Flutter: calling your backend
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<String> sendMessage(String message, String sessionId) async {
final response = await http.post(
Uri.parse('https://your-api.com/chat/'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'message': message,
'session_id': sessionId,
}),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return data['reply'];
}
throw Exception('Failed to get response');
}
What you can build with this
A support bot for a SaaS, an FAQ assistant for an online store, a document analyzer for a legal app, a product recommender. The API call is the easy part. Most of the work goes into the system prompt, into limiting what the model can see and do, and into keeping costs under control.
Thinking about a chatbot for your customers? Read the WhatsApp chatbot guide for Tunisian businesses