Back to Tutorials

Integrate GPT-5.5 into Expo React Native

Add a proper LLM feature to your mobile app: a secure backend endpoint, a small Expo chat screen, and production checks that avoid the common API-key-in-the-bundle mistake.

May 27, 2026 10 min read Paddy Byrne
Expo React Native OpenAI GPT-5.5 Responses API

The short version

Use GPT-5.5 through the OpenAI Responses API, but do not call OpenAI directly from your Expo app. Put your API key on a backend you control, then let the mobile app call that backend.

The current OpenAI guidance positions GPT-5.5 as the best default for complex production workflows, including customer-facing assistants, grounded experiences, and tool-heavy flows. For an Expo app, the architecture matters as much as the model choice: mobile bundles are not a safe place for API secrets.

1. Use the right architecture

The mobile app should only know about your own API URL. Your backend should own the OpenAI key, request validation, rate limits, moderation policy, logging, and model settings.

  • Expo app: collects the user prompt, renders state, and calls your API.
  • Backend endpoint: authenticates the app/user, validates input, and calls OpenAI.
  • OpenAI Responses API: runs GPT-5.5 and returns text for your product experience.

You can host the backend with Express, Next.js route handlers, Firebase Functions, Supabase Edge Functions, Cloudflare Workers, or any server you already use. The shape is the same.

2. Create a tiny backend proxy

Here is a minimal Express endpoint. It keeps the API key in process.env.OPENAI_API_KEY, accepts a prompt from the app, and asks GPT-5.5 for a concise mobile-friendly answer.

import express from "express"; const app = express(); app.use(express.json()); app.post("/api/assistant", async (req, res) => { const prompt = String(req.body.prompt || "").trim(); if (!prompt) { return res.status(400).json({ error: "Prompt is required." }); } if (prompt.length > 2000) { return res.status(400).json({ error: "Prompt is too long." }); } const response = await fetch("https://api.openai.com/v1/responses", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${process.env.OPENAI_API_KEY}`, }, body: JSON.stringify({ model: "gpt-5.5", reasoning: { effort: "low" }, text: { verbosity: "low" }, instructions: "You are a helpful assistant inside a mobile app. Be clear, concise, and useful.", input: prompt, }), }); if (!response.ok) { return res.status(502).json({ error: "The assistant is unavailable." }); } const data = await response.json(); res.json({ answer: data.output_text }); }); app.listen(3000);

For production, add user authentication and per-user rate limits before deploying this. A public unauthenticated endpoint that forwards prompts to an LLM will get expensive quickly.

3. Call it from Expo

On the Expo side, treat the LLM call like any other network request. Keep a loading state, show errors, and make the endpoint configurable so development, staging, and production can point at different hosts.

import { useState } from "react"; import { ActivityIndicator, Button, SafeAreaView, Text, TextInput, View } from "react-native"; const API_URL = process.env.EXPO_PUBLIC_API_URL; export default function AssistantScreen() { const [prompt, setPrompt] = useState(""); const [answer, setAnswer] = useState(""); const [loading, setLoading] = useState(false); const [error, setError] = useState(""); async function askAssistant() { setLoading(true); setError(""); setAnswer(""); try { const response = await fetch(`${API_URL}/api/assistant`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ prompt }), }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || "Something went wrong."); } setAnswer(data.answer); } catch (err) { setError(err instanceof Error ? err.message : "Something went wrong."); } finally { setLoading(false); } } return ( <SafeAreaView style={{ flex: 1, padding: 20 }}> <View style={{ gap: 16 }}> <TextInput value={prompt} onChangeText={setPrompt} placeholder="Ask the assistant..." multiline style={{ minHeight: 120, padding: 12, borderWidth: 1, borderRadius: 8 }} /> <Button title="Ask" onPress={askAssistant} disabled={loading || !prompt.trim()} /> {loading ? <ActivityIndicator /> : null} {error ? <Text style={{ color: "crimson" }}>{error}</Text> : null} {answer ? <Text>{answer}</Text> : null} </View> </SafeAreaView> ); }

The EXPO_PUBLIC_ variable is fine for your own API base URL, because it is not secret. Never put OPENAI_API_KEY or any server credential in an Expo public variable.

4. Pick sensible model settings

For most in-app assistants, start with a restrained configuration and tune from there:

  • Model: gpt-5.5 for the strongest current general-purpose experience.
  • Reasoning effort: low for quick mobile interactions; move to medium when answers need more careful planning.
  • Verbosity: low when screen space is tight; use medium for richer explanations.
  • Instructions: define the product outcome, tone, safety boundaries, and answer shape.

Do not over-prompt at the start. GPT-5.5 works well with outcome-first instructions: say what the assistant should achieve, what it must avoid, and what a good answer looks like.

5. Add production guardrails

Before shipping the feature, add the boring pieces that keep the exciting part healthy:

  • Authenticate users before they can call the assistant endpoint.
  • Rate limit by user, device, IP address, or subscription tier.
  • Validate prompt length and reject empty or abusive input early.
  • Log request IDs, latency, status, model, and token usage, but avoid storing sensitive user content unless your privacy policy allows it.
  • Give the app a graceful fallback message for network failures, server errors, and model timeouts.
  • Run real examples through the feature before changing prompts or reasoning settings.

Final checklist

When this is ready, your Expo app should have no OpenAI secret in the client bundle, one clear API route for assistant requests, and a model configuration you can improve without publishing a new mobile build.

# Mobile app EXPO_PUBLIC_API_URL=https://your-api.example.com # Backend only OPENAI_API_KEY=sk-...

That separation is the whole trick. The app stays lightweight, the backend stays in control, and GPT-5.5 can improve the product without turning your mobile bundle into a security problem.