To integrate a third-party API or SDK in Lovable, follow this sequence: install the SDK by prompting Lovable with the package name, store your API key in Cloud tab then Secrets, create a Supabase Edge Function for server-side API calls that need secret keys, and call the Edge Function from your frontend. For client-side SDKs (like Stripe.js or Google Maps), tell Lovable to add the script tag to index.html and initialize the SDK in a React component.
Why integrating third-party APIs and SDKs requires careful setup in Lovable
Third-party APIs and SDKs come in two categories that require different integration approaches in Lovable. Client-side SDKs (like Stripe.js, Google Maps JavaScript API, or Firebase) load directly in the browser and are configured with publishable keys that are safe to expose. Server-side APIs (like OpenAI, Twilio, or payment processing) require secret keys that must never appear in frontend code. The most common mistake is putting a secret API key in a VITE_ environment variable or directly in React component code. Variables prefixed with VITE_ are embedded at build time and shipped to every browser. Anyone who inspects the page source can extract your API key and use it, potentially running up charges on your account. For server-side APIs, the correct pattern is: store the API key in Cloud tab Secrets, create a Supabase Edge Function that makes the API call using the secret, and have your frontend call the Edge Function. The API key never leaves the server. For client-side SDKs, you can safely use publishable keys in VITE_ variables, but the SDK must be properly initialized and loaded in the correct order.
- Secret API keys exposed in frontend code — anyone can extract them from the browser
- SDK loaded before initialization — the SDK script has not finished loading when your code tries to use it
- Missing CORS headers — server-side APIs reject browser requests due to Cross-Origin policy
- Wrong SDK version — the package installed is not compatible with Lovable's React/Vite stack
- No error handling — API failures crash the component instead of showing a user-friendly message
Error messages you might see
ReferenceError: Stripe is not definedThe Stripe.js script has not finished loading when your component tries to use it. Make sure the Stripe script tag is in index.html and use a loading check before accessing the Stripe global variable.
Error: Invalid API key provided: sk-••••••You are sending a secret key from the frontend, or the key stored in Secrets is incorrect. Secret keys (starting with sk-) must only be used in Edge Functions, never in frontend code. Publishable keys (starting with pk-) are safe for the frontend.
TypeError: sdk.initialize is not a functionThe SDK was imported but the API has changed between versions, or you are importing the wrong module. Check the SDK documentation for the correct import syntax for your version.
Before you start
- A Lovable project open in the editor
- An API key or credentials from the third-party service you want to integrate
- The SDK name or API documentation URL for the service
- A Supabase connection (Lovable Cloud or self-hosted) for server-side API calls
How to fix it
Store your API key in the correct location
Secret keys in frontend code are visible to every user — Lovable Secrets keep them encrypted on the server
Store your API key in the correct location
Secret keys in frontend code are visible to every user — Lovable Secrets keep them encrypted on the server
Determine whether your API key is a publishable key (safe for browsers) or a secret key (must be server-side only). Publishable keys (like Stripe's pk_ key or Google Maps API key) can go in Cloud tab, then Secrets, and be accessed via VITE_ environment variables. Secret keys (like OpenAI's sk_ key or Twilio auth tokens) must go in Cloud tab, then Secrets, and be accessed only from Supabase Edge Functions. To add a secret: click the + button next to Preview, open Cloud tab, navigate to Secrets, click Add Secret, enter the name and value.
// DANGEROUS: Secret key hardcoded in frontend componentconst openai = new OpenAI({ apiKey: "sk-abc123secretkey"});// ALSO DANGEROUS: Secret key in a VITE_ variableconst apiKey = import.meta.env.VITE_OPENAI_API_KEY;// SAFE: Publishable key in VITE_ variable (for client-side SDKs only)const stripePublishableKey = import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY;// SAFE: Secret key stored in Cloud tab → Secrets// Name: OPENAI_API_KEY// Value: sk-abc123secretkey// This key is only accessible from Edge FunctionsExpected result: Your API keys are stored securely. Publishable keys are in VITE_ variables for frontend use. Secret keys are in Lovable Secrets for Edge Function use only.
Install the SDK package through a Lovable prompt
Lovable has no terminal — packages are installed by telling the AI to use them
Install the SDK package through a Lovable prompt
Lovable has no terminal — packages are installed by telling the AI to use them
Prompt Lovable in Agent Mode with the exact package name: 'Install the @stripe/stripe-js npm package and set up the Stripe provider in my app.' Lovable handles the npm installation and integration. For SDKs that load via script tag (like Google Maps), prompt: 'Add the Google Maps JavaScript API script tag to index.html with my API key from the VITE_GOOGLE_MAPS_KEY environment variable.'
// No SDK installed — you need to tell Lovable which package to use// Prompt example for npm package SDK:// "Install the @stripe/stripe-js and @stripe/react-stripe-js// npm packages. Initialize the Stripe provider in @src/App.tsx// using the VITE_STRIPE_PUBLISHABLE_KEY environment variable.// Wrap the Router component with the Stripe Elements provider."// Prompt example for script tag SDK:// "Add the Google Maps JavaScript API script to index.html.// Use the VITE_GOOGLE_MAPS_KEY environment variable for the// API key. Create a reusable GoogleMap component in// @src/components/GoogleMap.tsx that displays an interactive map."Expected result: The SDK is installed and initialized in your project. The relevant import statements and provider wrappers are in place.
Create an Edge Function for server-side API calls
APIs requiring secret keys must be called from the server — the Edge Function acts as a secure proxy
Create an Edge Function for server-side API calls
APIs requiring secret keys must be called from the server — the Edge Function acts as a secure proxy
For APIs that need secret keys (OpenAI, Twilio, payment processing), create a Supabase Edge Function. Prompt Lovable: 'Create a Supabase Edge Function called call-openai that reads the OPENAI_API_KEY from secrets, accepts a POST request with a prompt parameter, calls the OpenAI chat completions API, and returns the response.' The function runs on the server where Secrets are accessible. Your frontend calls this function using supabase.functions.invoke(). If you are integrating multiple APIs each requiring their own Edge Function and authentication flow, RapidDev's engineers can set up the complete integration architecture for you.
// Frontend code calling OpenAI directly — UNSAFE, exposes secret keyconst response = await fetch("https://api.openai.com/v1/chat/completions", { method: "POST", headers: { "Authorization": `Bearer ${import.meta.env.VITE_OPENAI_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ model: "gpt-4", messages: [{ role: "user", content: prompt }] })});// Edge Function: supabase/functions/call-openai/index.tsimport { serve } from "https://deno.land/std@0.168.0/http/server.ts";serve(async (req) => { try { const { prompt } = await req.json(); const apiKey = Deno.env.get("OPENAI_API_KEY"); if (!apiKey) throw new Error("OPENAI_API_KEY secret not set"); const response = await fetch("https://api.openai.com/v1/chat/completions", { method: "POST", headers: { "Authorization": `Bearer ${apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ model: "gpt-4", messages: [{ role: "user", content: prompt }], }), }); const data = await response.json(); return new Response(JSON.stringify(data), { headers: { "Content-Type": "application/json" }, }); } catch (error) { console.error("OpenAI API error:", error.message); return new Response(JSON.stringify({ error: error.message }), { status: 500, headers: { "Content-Type": "application/json" }, }); }});Expected result: The OpenAI API is called from the server-side Edge Function. The secret key never appears in frontend code or browser network requests.
Call the Edge Function from your React component
The frontend sends requests to your Edge Function proxy — never directly to the third-party API
Call the Edge Function from your React component
The frontend sends requests to your Edge Function proxy — never directly to the third-party API
In your React component, use supabase.functions.invoke() to call your Edge Function. This sends the request through Supabase's infrastructure, which handles authentication and CORS automatically. Add loading states, error handling, and user feedback to create a polished experience.
// Calling third-party API directly from frontend — CORS error or exposed keyconst result = await fetch("https://api.openai.com/v1/...", { ... });import { useState } from "react";import { supabase } from "@/integrations/supabase/client";import { Button } from "@/components/ui/button";function AIChat() { const [response, setResponse] = useState(""); const [loading, setLoading] = useState(false); const askAI = async (prompt: string) => { setLoading(true); try { const { data, error } = await supabase.functions.invoke("call-openai", { body: { prompt }, }); if (error) throw error; setResponse(data.choices[0].message.content); } catch (err) { console.error("AI request failed:", err); setResponse("Sorry, something went wrong. Please try again."); } finally { setLoading(false); } }; return ( <div> <Button onClick={() => askAI("Hello!")} disabled={loading}> {loading ? "Thinking..." : "Ask AI"} </Button> {response && <p className="mt-4">{response}</p>} </div> );}Expected result: The AI chat feature works through the Edge Function proxy. API calls are secure, with proper loading states and error handling.
Complete code example
1import { useState, useCallback } from "react";2import { supabase } from "@/integrations/supabase/client";34interface UseExternalApiOptions {5 functionName: string;6}78interface ApiState<T> {9 data: T | null;10 error: string | null;11 loading: boolean;12}1314export function useExternalApi<T = any>({ functionName }: UseExternalApiOptions) {15 const [state, setState] = useState<ApiState<T>>({16 data: null,17 error: null,18 loading: false,19 });2021 const invoke = useCallback(22 async (body: Record<string, any>) => {23 setState({ data: null, error: null, loading: true });2425 try {26 const { data, error } = await supabase.functions.invoke(functionName, {27 body,28 });2930 if (error) {31 throw new Error(error.message || "API call failed");32 }3334 setState({ data: data as T, error: null, loading: false });35 return data as T;36 } catch (err) {37 const message = err instanceof Error ? err.message : "Unknown error";38 console.error(`${functionName} error:`, message);39 setState({ data: null, error: message, loading: false });40 return null;41 }42 },43 [functionName]44 );4546 return {47 ...state,48 invoke,49 // Reset state between different API calls50 reset: () => setState({ data: null, error: null, loading: false }),51 };52}Best practices to prevent this
- Classify every API key as publishable (safe for frontend) or secret (Edge Function only) before integrating
- Store all API keys in Cloud tab then Secrets — never hardcode them in source files
- Use Supabase Edge Functions as a proxy for any API that requires secret keys
- Add loading states and error handling to every API integration — show the user what is happening
- Test the integration in the Lovable preview before publishing — check the browser console for errors
- Use the VITE_ prefix only for publishable keys that are genuinely safe to expose in the browser
- Create a reusable hook (like useExternalApi) for consistent API call patterns across your app
- Check the SDK documentation for the correct initialization pattern — some require script tags, others are npm packages
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to integrate [service name] into my Lovable (lovable.dev) project. My project uses Vite + React + TypeScript + Supabase. Service details: - API documentation URL: [url] - Key type: [publishable / secret / both] - What I want to build: [describe the feature] Please: 1. Determine if I need a client-side SDK, server-side API call, or both 2. Show me where to store each API key in Lovable (Secrets vs VITE_ variables) 3. If server-side: write the Supabase Edge Function code 4. If client-side: show the React component initialization 5. Write the frontend code that connects everything 6. Add error handling and loading states
Integrate [service name] into my project. Store the API key named [KEY_NAME] that I have added to Cloud tab Secrets. Create a Supabase Edge Function called [function-name] that: 1) Reads the API key from secrets. 2) Accepts a POST request with [describe parameters]. 3) Calls the [service] API at [endpoint URL]. 4) Returns the response as JSON with proper error handling. Then update @src/components/[Component].tsx to call this Edge Function using supabase.functions.invoke() with loading and error states.
Frequently asked questions
How do I add a third-party SDK to my Lovable project?
Prompt Lovable with the exact package name: 'Install the [package-name] npm package and integrate it into [component].' For script-tag SDKs, ask Lovable to add the script to index.html. Store API keys in Cloud tab then Secrets, not in code.
Can I use Stripe in a Lovable project?
Yes. Install @stripe/stripe-js and @stripe/react-stripe-js for the frontend (using the publishable key). For payment processing, create a Supabase Edge Function that uses the Stripe secret key to create checkout sessions and handle webhooks.
How do I integrate OpenAI with Lovable?
Store your OpenAI API key in Cloud tab then Secrets (it is a secret key, never for frontend use). Create a Supabase Edge Function that reads the key and calls the OpenAI API. Your React component calls the Edge Function using supabase.functions.invoke().
Why do I get CORS errors when calling a third-party API from Lovable?
Browsers enforce Cross-Origin Resource Sharing restrictions on direct API calls. The third-party server does not include Lovable's domain in its allowed origins. Fix this by routing the API call through a Supabase Edge Function, which runs server-side and bypasses CORS entirely.
Is it safe to put API keys in VITE_ environment variables?
Only for publishable keys that are designed to be public (like Stripe's pk_ key or Google Maps API key). Secret keys must never go in VITE_ variables because they are embedded in the JavaScript bundle and visible to anyone who loads your site.
What if I can't get the SDK integration working?
Third-party integrations often involve SDK initialization, authentication flows, webhook handling, and error management across multiple files. RapidDev's engineers have integrated dozens of third-party services into Lovable projects and can handle the complete setup.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your issue.
Book a free consultation