Skip to main content
RapidDev - Software Development Agency
lovable-integrationsEdge Function Integration

How to Integrate Lovable with OpenAI GPT

Add OpenAI GPT models to your Lovable app by creating a Supabase Edge Function that calls the OpenAI Chat Completions API. Store your OpenAI API key in Cloud → Secrets via Deno.env.get(), build Edge Functions for chat, structured outputs, and streaming responses, then call them from your React frontend using supabase.functions.invoke(). Use OpenAI when you need GPT-4o, function calling, structured JSON outputs, or model control beyond what Lovable AI's built-in Gemini 3 Flash offers.

What you'll learn

  • How to store your OpenAI API key securely in Cloud → Secrets and access it in Edge Functions
  • How to write an Edge Function that calls the OpenAI Chat Completions API with GPT-4o
  • How to implement streaming responses for real-time token-by-token output in your frontend
  • How to use OpenAI's structured output feature to extract typed JSON from model responses
  • When to use OpenAI versus Lovable AI's built-in Gemini 3 Flash connector
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate18 min read30 minutesAI/MLMarch 2026RapidDev Engineering Team
TL;DR

Add OpenAI GPT models to your Lovable app by creating a Supabase Edge Function that calls the OpenAI Chat Completions API. Store your OpenAI API key in Cloud → Secrets via Deno.env.get(), build Edge Functions for chat, structured outputs, and streaming responses, then call them from your React frontend using supabase.functions.invoke(). Use OpenAI when you need GPT-4o, function calling, structured JSON outputs, or model control beyond what Lovable AI's built-in Gemini 3 Flash offers.

Add GPT-4o and OpenAI features to your Lovable app beyond built-in AI

Lovable includes a built-in AI connector powered by Google's Gemini 3 Flash model — available as a native shared connector with zero configuration. For many use cases, Lovable AI is the right choice: it requires no API key, no Edge Function code, and no external billing. However, some applications have requirements that Lovable AI's Gemini 3 Flash connector does not meet: access to GPT-4o's specific capabilities, OpenAI's structured output feature for extracting typed JSON from model responses, function calling for integrating AI with external APIs, vision analysis of uploaded images, or fine-tuned models trained on your proprietary data.

For these use cases, integrating OpenAI directly via Edge Functions gives you the full OpenAI API surface with complete model control. The integration is clean: your OpenAI API key lives in Cloud → Secrets, a Supabase Edge Function calls the Chat Completions API using the openai npm package imported from esm.sh, and your React frontend calls the Edge Function via supabase.functions.invoke(). Streaming responses — where the model outputs text token-by-token as it generates — are supported through Deno's readable stream handling and can create a ChatGPT-like experience in your Lovable app.

The decision framework for Lovable AI versus OpenAI: use Lovable AI (Gemini 3 Flash) for general-purpose text generation, summaries, chatbots, and sentiment analysis where you do not need specific model control. Use OpenAI when you need GPT-4o's quality, function calling, structured outputs, vision capabilities, fine-tuned models, or when your users are more familiar with GPT's style and capabilities.

Integration method

Edge Function Integration

OpenAI GPT integrates with Lovable through Supabase Edge Functions that call the OpenAI Chat Completions API server-side. Your OpenAI API key is stored in Cloud → Secrets and accessed via Deno.env.get('OPENAI_API_KEY'). The Edge Function handles model selection, system prompts, message history, and optional streaming, while the React frontend calls the function via supabase.functions.invoke() and renders the response.

Prerequisites

  • A Lovable account with an active Lovable Cloud project
  • An OpenAI account with a funded API key (at platform.openai.com — new accounts get $5 free credit)
  • Your OpenAI API key from platform.openai.com → API Keys (starts with sk-proj- or sk-)
  • Basic understanding of which OpenAI model you need (GPT-4o for highest quality, GPT-4o-mini for lower cost, o3-mini for reasoning tasks)

Step-by-step guide

1

Store your OpenAI API key in Cloud → Secrets

Your OpenAI API key is the most important credential to protect in this integration. A leaked API key can result in significant unexpected charges — someone who finds your key can generate text at your expense, and OpenAI charges per token, so a badly exposed key in a public repository has resulted in four-figure bills for developers who discovered the exposure too late. Lovable's security system blocks approximately 1,200 hardcoded API keys per day, but the safest practice is never giving the system a chance to catch the mistake. To store your key, click the '+' icon next to the Preview label at the top of the Lovable editor. In the Cloud panel that opens, click the 'Secrets' tab. Click 'Add new secret'. Add: - Name: OPENAI_API_KEY — Value: your OpenAI API key (starts with sk-proj- for project keys or sk- for legacy personal keys) Also consider adding: - Name: OPENAI_MODEL — Value: gpt-4o (or gpt-4o-mini for lower cost per token) Storing the model name as a secret (or VITE_OPENAI_MODEL as a build-time env var) makes it easy to switch models across all your Edge Functions by updating one value rather than searching through code. IMPORTANT: Never paste your API key into Lovable's chat. On the free tier, Lovable chat history is publicly accessible. Even on paid tiers, keys pasted in chat can end up in your Git commit history. The Secrets panel is the only safe place for OpenAI API keys.

Pro tip: Set a spending limit in your OpenAI account at platform.openai.com → Settings → Billing → Usage limits. A $10-20 monthly hard limit prevents unexpected bills while you build and test.

Expected result: OPENAI_API_KEY (and optionally OPENAI_MODEL) are stored in Cloud → Secrets with masked values. The API key is not visible in any code, chat history, or Git commits.

2

Create a basic Chat Completions Edge Function

With your API key secured, create the Edge Function that calls OpenAI's Chat Completions API. The openai npm package is available from esm.sh with full TypeScript types and works natively in Deno's environment. The package handles request formatting, response parsing, and error handling, making it significantly more ergonomic than raw fetch calls to the API. The Edge Function accepts a messages array (the conversation history in OpenAI's format) and an optional system prompt override. It reads the model from the OPENAI_MODEL secret (defaulting to gpt-4o-mini for cost efficiency during development) and returns the model's response as JSON. For a simple one-shot AI feature (not a multi-turn chat), the messages array will contain just a single user message. For a conversational interface, the frontend maintains the message history in React state and passes the full history on each request so the model has context from previous turns. To create this Edge Function, open Lovable's chat and paste the prompt below. Lovable will create the file, deploy it, and show you how to call it from the frontend.

Lovable Prompt

Create a Supabase Edge Function at supabase/functions/openai-chat/index.ts that calls the OpenAI Chat Completions API. Import the openai package from esm.sh. Read OPENAI_API_KEY and OPENAI_MODEL (default to gpt-4o-mini) from Deno.env.get. Accept a POST request with 'messages' array and optional 'systemPrompt' string. Call the chat completions endpoint and return the assistant's message content as JSON. Include CORS headers and error handling.

Paste this in Lovable chat

supabase/functions/openai-chat/index.ts
1// supabase/functions/openai-chat/index.ts
2import OpenAI from 'https://esm.sh/openai@4';
3
4const corsHeaders = {
5 'Access-Control-Allow-Origin': '*',
6 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
7};
8
9const DEFAULT_SYSTEM_PROMPT = 'You are a helpful assistant. Be concise and friendly.';
10
11Deno.serve(async (req) => {
12 if (req.method === 'OPTIONS') return new Response('ok', { headers: corsHeaders });
13
14 try {
15 const { messages, systemPrompt } = await req.json();
16
17 if (!Array.isArray(messages) || messages.length === 0) {
18 return new Response(JSON.stringify({ error: 'messages array is required' }), {
19 status: 400,
20 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
21 });
22 }
23
24 const openai = new OpenAI({ apiKey: Deno.env.get('OPENAI_API_KEY')! });
25 const model = Deno.env.get('OPENAI_MODEL') || 'gpt-4o-mini';
26
27 const completion = await openai.chat.completions.create({
28 model,
29 messages: [
30 { role: 'system', content: systemPrompt || DEFAULT_SYSTEM_PROMPT },
31 ...messages,
32 ],
33 max_tokens: 1000,
34 temperature: 0.7,
35 });
36
37 const content = completion.choices[0].message.content;
38 return new Response(JSON.stringify({ content, usage: completion.usage }), {
39 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
40 });
41 } catch (error) {
42 console.error('OpenAI error:', error);
43 const status = (error as { status?: number }).status ?? 500;
44 return new Response(JSON.stringify({ error: String(error) }), {
45 status,
46 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
47 });
48 }
49});

Pro tip: Default to gpt-4o-mini during development — it costs approximately 20x less than gpt-4o and is fast enough for testing. Switch to gpt-4o for production if quality is important for your use case.

Expected result: The openai-chat Edge Function is deployed. A test invocation with a messages array returns the model's response text. Cloud → Logs shows successful 200 responses from the OpenAI API.

3

Add streaming support for real-time token output

Streaming transforms the user experience for longer AI responses. Instead of waiting 3-10 seconds for a complete response, text appears word-by-word as the model generates it — exactly like ChatGPT. The OpenAI SDK supports streaming with the stream option, and Deno's edge runtime handles streaming responses natively. The streaming Edge Function below uses OpenAI's stream mode and returns a ReadableStream that the frontend can consume. The frontend uses the Fetch API's streaming reader to process each chunk as it arrives and update the UI in real time. Note that supabase.functions.invoke() does not natively support streaming response consumption — for streaming, call the Edge Function URL directly using fetch(), which gives you access to the ReadableStream. The Edge Function URL follows the pattern: https://{your-project-ref}.supabase.co/functions/v1/openai-chat-stream. For a polished streaming chat interface, Lovable can generate the complete frontend component with the streaming fetch call, token-by-token state updates, and automatic scrolling. Describe what you need in the chat and Lovable will handle the component logic.

Lovable Prompt

Create a streaming version of the OpenAI Edge Function at supabase/functions/openai-chat-stream/index.ts that uses OpenAI SDK's stream mode and returns a text/event-stream response. Then build a chat interface React component that calls this function via fetch (not supabase.functions.invoke), reads the streaming response body, appends each token chunk to the current message in React state as it arrives, and auto-scrolls to the latest message. Include a loading indicator that shows when the stream starts and hides when it ends.

Paste this in Lovable chat

supabase/functions/openai-chat-stream/index.ts
1// supabase/functions/openai-chat-stream/index.ts
2import OpenAI from 'https://esm.sh/openai@4';
3
4const corsHeaders = {
5 'Access-Control-Allow-Origin': '*',
6 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
7};
8
9Deno.serve(async (req) => {
10 if (req.method === 'OPTIONS') return new Response('ok', { headers: corsHeaders });
11
12 try {
13 const { messages, systemPrompt } = await req.json();
14 const openai = new OpenAI({ apiKey: Deno.env.get('OPENAI_API_KEY')! });
15 const model = Deno.env.get('OPENAI_MODEL') || 'gpt-4o-mini';
16
17 const stream = await openai.chat.completions.create({
18 model,
19 messages: [
20 { role: 'system', content: systemPrompt || 'You are a helpful assistant.' },
21 ...messages,
22 ],
23 stream: true,
24 max_tokens: 2000,
25 });
26
27 const readableStream = new ReadableStream({
28 async start(controller) {
29 const encoder = new TextEncoder();
30 try {
31 for await (const chunk of stream) {
32 const text = chunk.choices[0]?.delta?.content || '';
33 if (text) {
34 controller.enqueue(encoder.encode(`data: ${JSON.stringify({ text })}\n\n`));
35 }
36 }
37 controller.enqueue(encoder.encode('data: [DONE]\n\n'));
38 } finally {
39 controller.close();
40 }
41 },
42 });
43
44 return new Response(readableStream, {
45 headers: {
46 ...corsHeaders,
47 'Content-Type': 'text/event-stream',
48 'Cache-Control': 'no-cache',
49 'Connection': 'keep-alive',
50 },
51 });
52 } catch (error) {
53 return new Response(JSON.stringify({ error: String(error) }), {
54 status: 500,
55 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
56 });
57 }
58});

Pro tip: When building the frontend streaming reader, check each chunk for the '[DONE]' sentinel value to know when to stop reading and update the UI state to 'not generating'.

Expected result: The streaming Edge Function returns tokens in real-time as Server-Sent Events. The frontend chat interface displays text appearing word-by-word. The experience is noticeably more responsive than waiting for a complete response.

4

Implement structured outputs for JSON data extraction

OpenAI's structured output feature (introduced with GPT-4o) guarantees that the model returns a valid JSON object matching a schema you define. This eliminates the parsing errors and 'model returned invalid JSON' problems common with prompt-based JSON generation. Structured outputs use JSON Schema to define the expected shape of the response. For a Lovable app, structured outputs are particularly useful for data extraction use cases — parsing contact information from pasted text, extracting product attributes from descriptions, converting user search queries into database filter parameters, or summarizing long form content into structured records. The Edge Function uses OpenAI's response_format option with json_schema to enforce the output format. Define the schema inline in the Edge Function or pass it as a parameter from the frontend for dynamic schemas. The parsed JSON is returned directly — no regex, no JSON.parse() error handling needed. After creating the Edge Function, ask Lovable to build the frontend form that calls it: 'Build a contact extraction form with a large textarea where users paste any text containing contact information. On submit, call the openai-extract Edge Function and display the extracted name, email, phone, and company fields in a preview card below the textarea with Edit buttons for each field and a Save to Contacts button.'

Lovable Prompt

Create a Supabase Edge Function at supabase/functions/openai-extract/index.ts that uses OpenAI structured outputs to extract contact information from text. Use response_format with json_schema to return a JSON object with fields: name (string), email (string), phone (string), company (string), notes (string). All fields optional except name. Use GPT-4o (not mini) for best extraction accuracy. Return the parsed JSON object.

Paste this in Lovable chat

supabase/functions/openai-extract/index.ts
1// supabase/functions/openai-extract/index.ts
2import OpenAI from 'https://esm.sh/openai@4';
3
4const corsHeaders = {
5 'Access-Control-Allow-Origin': '*',
6 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
7};
8
9const contactSchema = {
10 name: 'contact_extraction',
11 schema: {
12 type: 'object',
13 properties: {
14 name: { type: 'string', description: 'Full name of the person' },
15 email: { type: 'string', description: 'Email address' },
16 phone: { type: 'string', description: 'Phone number in any format' },
17 company: { type: 'string', description: 'Company or organization name' },
18 notes: { type: 'string', description: 'Any other relevant information' },
19 },
20 required: ['name'],
21 additionalProperties: false,
22 },
23 strict: true,
24};
25
26Deno.serve(async (req) => {
27 if (req.method === 'OPTIONS') return new Response('ok', { headers: corsHeaders });
28
29 try {
30 const { text } = await req.json();
31 if (!text?.trim()) {
32 return new Response(JSON.stringify({ error: 'text is required' }), {
33 status: 400,
34 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
35 });
36 }
37
38 const openai = new OpenAI({ apiKey: Deno.env.get('OPENAI_API_KEY')! });
39
40 const completion = await openai.chat.completions.create({
41 model: 'gpt-4o',
42 messages: [
43 { role: 'system', content: 'Extract contact information from the provided text. Only include fields that are clearly present in the text.' },
44 { role: 'user', content: text },
45 ],
46 response_format: { type: 'json_schema', json_schema: contactSchema },
47 });
48
49 const extracted = JSON.parse(completion.choices[0].message.content!);
50 return new Response(JSON.stringify({ contact: extracted }), {
51 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
52 });
53 } catch (error) {
54 console.error('Extraction error:', error);
55 return new Response(JSON.stringify({ error: String(error) }), {
56 status: 500,
57 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
58 });
59 }
60});

Pro tip: Structured outputs with strict: true guarantee valid JSON matching the schema, but they require gpt-4o or gpt-4o-mini — they are not available on older models like gpt-3.5-turbo.

Expected result: The openai-extract Edge Function returns a parsed JSON object matching the contact schema. Testing with sample contact text returns correctly structured data with all identifiable fields populated.

5

Build the frontend AI feature and monitor usage costs

With the Edge Functions deployed, build the Lovable frontend components that surface the AI features to your users. Open Lovable's chat and describe the AI-powered feature you want — Lovable will generate the React components, form handling, state management, and Edge Function calls. For a chat interface: describe the conversation UI you need, the system prompt context for your use case, and any custom styling. Lovable will generate a complete chat component with message history, loading states, error handling, and the supabase.functions.invoke() call wired up. For structured extraction: describe the input form and the display of extracted results. Lovable will generate the textarea, submit handler, loading state, and result display component. An important operational consideration is OpenAI API costs. GPT-4o costs approximately $2.50 per million input tokens and $10 per million output tokens as of March 2026. For user-facing features where untrusted users can send arbitrary-length messages, add input length validation in your Edge Function (reject inputs over a configurable token limit) and consider adding rate limiting per user ID to prevent abuse. Log the token usage returned by the API (completion.usage) to Cloud → Logs so you can monitor costs per request and identify expensive queries early. For applications with high AI feature usage or complex prompt engineering requirements, RapidDev's team can help optimize prompts for cost and quality, implement caching for common queries, and design rate limiting strategies for production scale.

Lovable Prompt

Build a full chat interface for this app that uses the openai-chat Edge Function. Include a message history display with different styles for user and assistant messages, a text input field at the bottom, a Send button, and a loading indicator while waiting for the response. Store the full conversation history in React state and send it with each request so GPT-4o has context. Add a Clear Chat button. Include a character counter showing token estimate (divide character count by 4 as approximation) to help users understand input length.

Paste this in Lovable chat

Pro tip: Add a MAX_INPUT_LENGTH check at the start of your Edge Function — reject requests where the total messages content exceeds 50,000 characters to prevent runaway costs from users pasting large documents.

Expected result: The AI chat interface or structured extraction feature works in the Lovable preview. Messages are sent to OpenAI via the Edge Function and responses display correctly. Cloud → Logs shows successful API calls with token usage data.

Common use cases

Build a ChatGPT-style chat interface with streaming responses

Add a conversational AI assistant to your Lovable app with real-time streaming output — text appears word-by-word as GPT-4o generates it, exactly like ChatGPT. The Edge Function handles the streaming response and the frontend displays tokens as they arrive, creating a highly responsive user experience that feels much faster than waiting for the complete response.

Lovable Prompt

Create an Edge Function that calls OpenAI GPT-4o with streaming enabled and a custom system prompt about our product. Build a chat interface component with a message history, an input field, and a Send button. As the response streams in, append tokens to the last assistant message in real-time. Show a typing indicator while the model is generating. Store the conversation history in React state so the model has context from previous messages.

Copy this prompt to try it in Lovable

Extract structured data from unstructured text using structured outputs

OpenAI's structured output feature forces GPT-4o to return a valid JSON object matching a schema you define — guaranteed, no parsing errors. This enables use cases like extracting contact information from email text, parsing invoice data from uploaded PDFs, converting natural language into database filter queries, or pulling structured product attributes from unformatted descriptions.

Lovable Prompt

Create an Edge Function that uses OpenAI's structured output feature to extract contact information from pasted text. The response should be a JSON object with fields: name, email, phone, company, and notes. Build a lead capture page where users paste any text containing contact info (email signature, LinkedIn bio, business card photo description) and the app extracts the structured data and saves it to the Supabase contacts table.

Copy this prompt to try it in Lovable

Add AI-powered document analysis with GPT-4 Vision

GPT-4o can analyze uploaded images — screenshots, product photos, charts, scanned documents, or UI mockups. Users upload an image to your Lovable app, it is stored in Supabase Storage, and an Edge Function sends the image URL to OpenAI's vision endpoint for analysis. This enables features like UI feedback tools, product photo description generators, or receipt parsing for expense tracking apps.

Lovable Prompt

Add an image analysis feature to this app. Users should be able to upload a product photo from their device. Store the image in Supabase Storage, then call an OpenAI GPT-4o Edge Function with the image URL to generate a product description and suggest a category and price range based on what GPT-4o sees in the image. Display the AI-generated description in an editable text area below the uploaded image.

Copy this prompt to try it in Lovable

Troubleshooting

Edge Function returns 'Error 401: Incorrect API key provided'

Cause: The OPENAI_API_KEY secret value is incorrect, the key has been revoked in the OpenAI dashboard, or the key was stored with extra whitespace or line break characters.

Solution: Go to platform.openai.com → API Keys and verify the key you stored is still active (not expired or revoked). Copy the key fresh from OpenAI and update the OPENAI_API_KEY secret in Cloud → Secrets. Make sure there are no leading or trailing spaces in the secret value. The new value takes effect on the next Edge Function invocation — no redeployment required.

Edge Function returns 'Error 429: Rate limit exceeded' or 'You exceeded your current quota'

Cause: Either the per-minute token rate limit for your OpenAI tier has been hit (rate limit error), or the API key's associated account has run out of credits or reached its spending limit (quota error).

Solution: For rate limits: add exponential backoff retry logic to the Edge Function, or implement a request queue. Rate limits reset per minute, so a short wait typically resolves temporary spikes. For quota errors: go to platform.openai.com → Settings → Billing and add credits or increase the monthly spending limit. For ongoing rate limit issues on high-traffic apps, consider upgrading to a higher OpenAI tier or using gpt-4o-mini which has higher rate limits than gpt-4o.

Streaming responses show text all at once instead of token-by-token

Cause: The frontend is collecting the entire stream before updating the UI, using supabase.functions.invoke() which buffers the complete response, or the ReadableStream reader is not updating React state on each chunk.

Solution: For streaming, use the native fetch() API directly (not supabase.functions.invoke()) to access the raw ReadableStream. Call response.body.getReader() and process each chunk individually, calling setState on each chunk to trigger React re-renders. Make sure the Edge Function returns Content-Type: text/event-stream and not application/json. The streaming code example in Step 3 shows the correct pattern.

Structured output Edge Function returns 'refusal' field instead of the expected JSON object

Cause: OpenAI's safety system determined the input contained content that violated the usage policies, or the requested extraction was deemed harmful. GPT-4o refuses the request and returns a refusal message rather than a JSON object.

Solution: Check the completion.choices[0].message.refusal field in the Edge Function before trying to parse the content. If refusal is non-null, return the refusal message to the frontend with an appropriate error status. For legitimate content that triggers false refusals, adjust the system prompt to provide context about the legitimate business use case.

typescript
1// Check for refusal before parsing
2const choice = completion.choices[0].message;
3if (choice.refusal) {
4 return new Response(JSON.stringify({ error: 'Content not processed', reason: choice.refusal }), {
5 status: 422,
6 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
7 });
8}
9const extracted = JSON.parse(choice.content!);

Best practices

  • Always use OPENAI_API_KEY from Deno.env.get() in Edge Functions — never hardcode API keys in code, never paste them into Lovable's chat, and never include them in VITE_ environment variables that are bundled into the frontend JavaScript.
  • Default to gpt-4o-mini during development to control costs — it is approximately 20x cheaper than gpt-4o and supports all the same features including structured outputs and function calling. Switch to gpt-4o in production only for use cases where quality is demonstrably better.
  • Add input length validation in Edge Functions to prevent runaway costs from users pasting large documents — check the combined length of all messages and reject requests exceeding your configured limit with a user-friendly error.
  • Log token usage from completion.usage to Cloud → Logs on every request — this data helps you identify expensive queries, monitor cost trends, and decide whether to switch models or add caching.
  • Use OpenAI's structured output feature instead of prompt-based JSON generation — structured outputs are guaranteed to be valid JSON matching your schema, while prompting the model to return JSON can produce malformed responses.
  • Set a spending limit in your OpenAI account at platform.openai.com → Settings → Billing before building user-facing features — a $20 monthly hard limit prevents unexpected bills from bugs or abuse without disrupting normal usage.
  • For conversational AI features, send the full message history with each request rather than just the latest user message — GPT-4o needs conversation context to provide coherent follow-up responses. Trim the history to the last 10-20 messages for very long conversations to stay within context limits.

Alternatives

Frequently asked questions

Should I use OpenAI or Lovable AI's built-in Gemini connector?

Use Lovable AI's built-in Gemini 3 Flash connector for general-purpose text generation, summaries, chatbots, and simple AI features — it requires zero configuration, no API key, and no Edge Function code. Use OpenAI when you specifically need GPT-4o's capabilities (structured outputs, function calling, vision, fine-tuned models), when your users expect GPT behavior, or when Gemini 3 Flash's quality is not meeting your use case requirements. OpenAI requires more setup but gives you full model control and access to the complete OpenAI API surface.

What does OpenAI cost per request for a typical chat message?

GPT-4o-mini costs approximately $0.15 per million input tokens and $0.60 per million output tokens. A typical chat message (200 input tokens, 300 output tokens) costs about $0.00021 — less than a quarter of a cent. GPT-4o costs approximately $2.50/$10 per million tokens, making the same message cost about $0.0035. For a Lovable app with 100 daily active users each sending 20 messages per day, gpt-4o-mini would cost roughly $0.04/day ($1.20/month). Scale this proportionally for your expected usage.

Can I use OpenAI function calling in a Lovable Edge Function?

Yes. OpenAI's function calling (now called tool_use) works in Deno Edge Functions using the openai npm package. Define your tools as JSON schemas in the Edge Function, pass them to the chat completions request in the tools array, and handle the model's tool_calls response when it decides to call a function. The Edge Function executes the function (calling a Supabase query, an external API, etc.) and returns the result to the model in a follow-up request. This is more complex to implement than simple completions but enables AI-powered agents that can query databases and call external services.

Why is my streaming response displaying all at once instead of word-by-word?

Streaming requires using the native fetch() API rather than supabase.functions.invoke() — the Supabase invoke helper buffers the complete response before returning it, which is why you see the full text at once. Call the Edge Function URL directly with fetch(), then use response.body.getReader() to read the stream chunk-by-chunk. Each chunk updates React state, which triggers a re-render and shows the incremental text. The streaming Edge Function example in Step 3 includes the complete server-side implementation.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.