The one rule that matters
Private API keys never go in browser code. Not in a component, not in a config file, not in a VITE_ variable. Anything shipped to the browser is readable by anyone who opens developer tools, and leaked keys get abused within hours.
Keys live server-side. Your front end calls your own server function; the server function calls the third party using the secret.
Browser → your server function → third-party API
(holds the secret)
Publishable keys — the ones a provider explicitly labels public, like a payment provider's publishable key or a maps key restricted by domain — are the only exception.
Step by step
1. Enable the backend so you have somewhere secret to keep the key and somewhere server-side to run the call.
2. Add the key as a secret. Ask for it by name and you will be prompted to paste the value securely:
Add a secret called WEATHER_API_KEY, then use it in a server function.
3. Ask for the integration in one clear prompt:
Create a server function that calls the OpenWeather current-weather endpoint using WEATHER_API_KEY. It takes a city name, validates the input, and returns only temperature, conditions and icon. Handle non-200 responses by returning a clear error message. Then show the result on the /weather page with loading and error states.
4. Test the failure paths, not just the happy path: a bad key, a missing city, the provider timing out. An integration that only works when everything is perfect will embarrass you in week one.
What to tell the AI about the API
The more of this you supply, the better the result:
- The exact endpoint URL and HTTP method.
- How authentication is sent — header name, bearer token, query parameter.
- An example request and an example response.
- Which fields you actually want to keep.
- Rate limits you must respect.
Link to the provider's docs page in the prompt. If the API is unusual, paste a sample response — the AI can then map fields exactly rather than guessing names.
Errors, rate limits and cost control
Ask for these explicitly; they are rarely added by default:
- Timeouts so a slow provider does not hang your page.
- A friendly error message instead of a blank screen.
- Caching for data that does not change every second — weather, exchange rates, product catalogues. This is also how you stay inside a free tier.
- Input validation before the outbound call, so junk input never costs you a paid request.
Webhooks — the other direction
When a provider needs to call you (a payment succeeded, a form was submitted, a job finished), you need a public endpoint:
Create a public webhook endpoint at /api/public/stripe. Verify the provider signature before processing anything, validate the payload, then update the order status.
Signature verification is mandatory. An unverified webhook endpoint is a public write API to your database.
Common integration mistakes
| Mistake | Consequence |
|---|---|
| Key in front-end code | Key stolen and billed against you |
| No error handling | Blank page whenever the provider hiccups |
| No caching | Free tier exhausted in a day |
| Returning the whole provider response | Leaks data you did not intend to expose |
| Unverified webhook | Anyone can post fake events to your app |
Integrations people ask for most
Payments, email sending, AI text and image generation, maps and geocoding, calendars, CRM sync, SMS, and spreadsheet exports. All follow the same shape: secret on the server, thin server function, narrow response, real error handling.
Start with one integration, get it fully working including failures, then add the next.
Frequently asked questions
- How do I connect an external API to Lovable?
- Enable the backend, store the key as a server-side secret, and ask for a server function that calls the API and returns only the fields your page needs.
- Where do I store an API key in Lovable?
- As a secret used by server-side code. Never in components or VITE_ variables, which are shipped to every visitor's browser.
- Can Lovable receive webhooks?
- Yes — create a public endpoint under /api/public and verify the provider's signature inside the handler before processing any data.
- How do I avoid blowing through an API free tier?
- Cache responses that do not change often, validate input before calling out, and add timeouts so retries do not stack up.
Go deeper
Related guides
Lovable Cloud — the backend you don't have to set up
Lovable Cloud gives your app a database, user accounts, file storage and server functions without creating a separate account or wiring keys. Here's what it includes and when you need it.
Lovable login — signing in, and adding login to your app
Two things people mean by Lovable login: getting into your own Lovable account, and adding user accounts to the app you are building. Both are covered here, step by step.
Lovable prompts that work — structure, templates and fixes
A repeatable prompt structure for Lovable, copy-paste templates for features, styling, bug fixes and refactors, and the phrases that stop unwanted changes.