/lovable-issues

Connecting External API Endpoints to Lovable Projects

Learn why Lovable fails to detect custom API endpoints, plus how to set them up and integrate APIs with proven best practices.

Book a free  consultation
4.9
Clutch rating 🌟
600+
Happy partners
17+
Countries served
190+
Team members
Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Book a free No-Code consultation

Why Lovable Can't Detect or Use Custom API Endpoints Properly

Lovable often can't detect or use custom API endpoints properly because the Preview/build environment is not the same as your local dev server: environment variables and Secrets aren't automatically imported, local dev proxies or servers (Vite/webpack proxies, Docker, local-only backends) don't run in Lovable, and CORS/origin/allowlist differences or build-time vs runtime environment baking cause the client to point to the wrong URL or fail at runtime.

 

Root causes (short)

 

  • Missing Secrets / env in Lovable: Local .env files aren't available in Lovable Preview unless values are configured in the project Secrets/Environment.
  • Dev-only proxies and local servers: Vite/webpack dev proxies, local backends, or Dockerized services that route "/api" on your machine are not present in the cloud Preview — Lovable runs the built app, not your local dev server.
  • Build-time vs runtime env mismatch: Some frameworks bake process.env/import.meta.env into the build. If those values aren't set in Lovable before the build, the compiled client will use defaults or undefined URLs.
  • CORS / origin and allowlist problems: Preview runs from a Lovable-hosted origin; APIs that restrict origins, IPs, or whitelist localhost will reject requests.
  • Missing serverless endpoints or improper routing: App code that expects an internal API route (Next/api, functions/) may not be deployed or built the same way in Preview, so endpoints are unreachable.
  • Incorrect absolute vs relative URLs: Hard-coded absolute URLs or assumptions about base path can point to localhost or a dev hostname instead of the deployed Preview host.

 

Concrete Lovable prompts to diagnose (paste each into Lovable chat)

 

// Prompt 1: find where API base URL is defined
// Search the repository for common env keys and client references and show matches.
Please search the repo for these tokens and return file paths with the matching lines: API_URL, API_BASE, NEXT_PUBLIC_API, VITE_API_URL, process.env., import.meta.env, fetch('/api'), axios.create, new URL(,).
Then open the top 3 files that look like API clients (show full file contents) and indicate whether the base URL is hard-coded, uses an env var, or is relative.

 

// Prompt 2: check Lovable Secrets/environment
// Confirm whether the env keys found above are configured in Lovable.
Open the project's Secrets/Environment settings in Lovable. List which secret names exist (masked values okay). For each env key referenced by the code (from Prompt 1), state if a matching secret exists. If not present, add a note explaining the likely runtime impact.

 

// Prompt 3: reproduce and capture Preview network errors
// Use the Preview Console/Network and collect exact details of failed API calls.
Open the Preview and run the user flow that triggers the failing API call. Copy the full network request URL, request headers, response status, response body or error, and any console CORS/errors. Paste those raw logs here.

 

// Prompt 4: detect dev-proxy or local-only routing
// Search for dev proxy/rewrites used only in local dev configurations.
Search for vite.config.*, webpack.config.*, next.config.js, and look for devServer.proxy, server.proxy, rewrites, or dev-only middleware. Show the relevant config block and explain whether this proxy would run in Lovable Preview (hint: it will not).

 

// Prompt 5: check for server/edge functions or API routes
// Verify whether API endpoints are part of the app and how they are built/deployed.
List files under pages/api, src/pages/api, api/, functions/, or server/ and show their contents. For each, state whether it's a Next/API route, serverless function, or a placeholder that requires external deployment.

 

// Prompt 6: flag build-time env usage
// Identify env keys used at build time vs runtime.
Search for process.env.<KEY> and import.meta.env.<KEY>. For each key used, mark if it's read during build (e.g., in top-level module scope) or at runtime (inside functions). Explain which ones must be set as Lovable Secrets before building/publishing.

 

// Prompt 7: note when terminal/CI is needed
// If analysis finds local-only services or native tooling, create a clear note for external steps.
If any dependency requires a local dev server, Docker, or terminal build step, create DEPLOY_NOTES.md in project root with a one-paragraph explanation: "This project depends on X which cannot run in Lovable Preview. To test fully, sync to GitHub and run Y locally or deploy to your target environment (terminal required)." Show the file contents.

Still stuck?
Copy this prompt into ChatGPT and get a clear, personalized explanation.

This prompt helps an AI assistant understand your setup and guide you through the fix step by step, without assuming technical knowledge.

AI AI Prompt

How to Set Up Custom API Endpoints in Lovable

Create a server-side route file inside your Lovable project (an API endpoint file under an /api or /pages/api folder depending on your framework), store any secret keys using Lovable’s Secrets UI, update the client to call that internal endpoint (fetch('/api/your-endpoint')), Preview to test, and Publish when ready. If you need native packages or a custom runtime that requires running terminal commands, export/sync to GitHub and perform installs/builds outside Lovable (terminal required).

 

Create the server endpoint file (paste this prompt into Lovable chat)

 

Paste into Lovable Chat Mode. Ask Lovable to detect framework and create the endpoint. This prompt instructs Lovable to add a server endpoint file and the handler code.

// Please create a server API endpoint in the correct location for this project.
// If this repo uses Next.js (package.json contains "next" or next.config.js exists), create:
//   src/pages/api/custom-endpoint.ts
// Otherwise create a generic serverless endpoint at:
//   api/custom-endpoint.ts
//
// Add the following TypeScript handler code in the new file.
// The handler reads process.env.EXTERNAL_API_KEY (set via Lovable Secrets UI).
// It proxies a request to https://example.com/data and returns JSON.

Create file: src/pages/api/custom-endpoint.ts  // or api/custom-endpoint.ts if not Next.js
Content:
// file: src/pages/api/custom-endpoint.ts
import type { NextApiRequest, NextApiResponse } from 'next'

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const key = process.env.EXTERNAL_API_KEY
  if (!key) {
    return res.status(500).json({ error: 'Missing server secret: EXTERNAL_API_KEY' })
  }
  // Proxy to external API using the secret
  const upstream = await fetch('https://example.com/data', {
    headers: { 'Authorization': `Bearer ${key}` }
  })
  const data = await upstream.json()
  return res.status(200).json({ ok: true, data })
}

 

Add the secret in Lovable Cloud Secrets UI (paste this instruction into chat as a reminder)

 

Use Lovable’s Secrets panel — this is UI work, not a file edit. Paste and follow this instruction in Lovable to create the secret.

// Open the Secrets panel in Lovable Cloud for the current project.
// Add a new secret with key: EXTERNAL_API_KEY
// Value: (paste your external API key or token)
// Scope: choose the environment(s) you will Preview/Publish to
// Save the secret.

 

Update client code to call the endpoint (paste this prompt into Lovable chat)

 

Tell Lovable to create/update a client helper that calls the new endpoint and to wire it into an existing page or component.

// Create file: src/lib/fetchCustom.ts
// Add a small wrapper the app can import and use.

Create file: src/lib/fetchCustom.ts
Content:
// file: src/lib/fetchCustom.ts
export async function fetchCustomData() {
  // This calls the internal endpoint we just added
  const res = await fetch('/api/custom-endpoint')
  if (!res.ok) throw new Error('Failed to fetch custom endpoint')
  return res.json()
}

// Update an example page/component that needs this behavior, e.g. src/pages/index.tsx
// Insert a simple useEffect call to fetch data on load and log it.

Update file: src/pages/index.tsx
Find: inside the main component function
Insert:
// file: src/pages/index.tsx (modified)
import { useEffect } from 'react'
import { fetchCustomData } from '../lib/fetchCustom'

useEffect(() => {
  fetchCustomData().then(console.log).catch(console.error)
}, [])

 

Preview and Publish the change (paste this instruction into Lovable chat)

 

Use Lovable’s Preview and Publish controls — this tests the server endpoint using the environment and secrets you set.

// In Lovable UI:
// 1. Click Preview. Load the page that triggers fetchCustomData.
// 2. Confirm the Preview console or response shows the proxied data.
// 3. If okay, click Publish to deploy with the configured secret in that deployment environment.

 

If you need new npm packages or native build steps (outside Lovable)

 

If the endpoint requires installing binaries or new packages that Lovable cannot add in-app, use GitHub sync/export and do the install/build outside Lovable.

 // Outside Lovable (terminal required):
 // 1. Export or sync the project to GitHub from Lovable.
 // 2. Clone locally, run npm install (or yarn), run build, push changes back to GitHub.
 // 3. Re-sync Lovable with the updated repo if you changed runtime configs.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Book a Free Consultation

Best Practices for Integrating Custom APIs in Lovable

The short answer: treat custom APIs as a well-encapsulated, configurable client + server-side proxy for secrets. Store credentials in Lovable Secrets, put timeouts/retries/type-checking in a small shared client module, call secret-backed endpoints only from server-side routes (or external serverless functions), and use Lovable Preview/Publish + GitHub sync only when you need CLI or extra deployment control.

 

Concrete Lovable prompts you can paste into Lovable Chat

 

  • Prompt — Create a resilient API client module

Please create a new file src/lib/apiClient.ts and add the following. This is a small shared wrapper with timeout, exponential backoff retry, typed JSON handling, and explicit errors. Use process.env.CUSTOM_API_BASE and process.env.CUSTOM_API_KEY for configuration (we'll add them to Lovable Secrets next).

// src/lib/apiClient.ts
// Small fetch wrapper for custom APIs with timeout, retries, and JSON handling
type FetchOptions = RequestInit & { retry?: number; timeoutMs?: number; useKey?: boolean; };

const DEFAULT_TIMEOUT = 8000;
const DEFAULT_RETRIES = 2;

function timeoutFetch(input: RequestInfo, init: RequestInit, ms: number) {
  // simple AbortController timeout
  const controller = new AbortController();
  const id = setTimeout(() => controller.abort(), ms);
  const merged = { ...init, signal: controller.signal };
  return fetch(input, merged).finally(() => clearTimeout(id));
}

async function fetchWithRetries(path: string, opts: FetchOptions = {}) {
  const base = process.env.CUSTOM_API_BASE || "";
  const url = base + path;
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT;
  const retries = opts.retry ?? DEFAULT_RETRIES;

  const headers: Record<string, string> = { ...(opts.headers as Record<string,string> || {}) };
  if (opts.useKey) {
    // use server-only key from env (do not expose to client-side bundle)
    const key = process.env.CUSTOM_API_KEY;
    if (!key) throw new Error("Missing CUSTOM_API_KEY in server environment");
    headers["Authorization"] = `Bearer ${key}`;
  }

  let attempt = 0;
  let backoff = 300;
  while (true) {
    attempt++;
    try {
      const res = await timeoutFetch(url, { ...opts, headers }, timeoutMs);
      const text = await res.text();
      const body = text ? JSON.parse(text) : null;
      if (!res.ok) {
        const err: any = new Error(`API ${res.status} ${res.statusText}`);
        err.status = res.status;
        err.body = body;
        throw err;
      }
      return body;
    } catch (err) {
      if (attempt > retries) throw err;
      // simple exponential backoff
      await new Promise(r => setTimeout(r, backoff));
      backoff *= 2;
    }
  }
}

export { fetchWithRetries };

 

  • Prompt — Add secrets using Lovable Cloud Secrets UI

Open Lovable Cloud > Secrets for this project and add the following keys (do not commit actual secrets to code):

  • CUSTOM_API_BASE — full base URL including protocol and trailing slash if you used it above.
  • CUSTOM_API_KEY — server API key (mark as secret).
After adding, return here and Preview to ensure process.env values are available during Preview/Publish.

 

  • Prompt — If your app is Next.js: create a server-side proxy route so secrets are never shipped to the browser

Only apply this if your project uses Next.js. Create src/pages/api/proxy.ts with this code. The frontend will call /api/proxy to avoid exposing CUSTOM_API_KEY.

// src/pages/api/proxy.ts
// Server-side proxy: forwards client requests to the external API using server secret.
import type { NextApiRequest, NextApiResponse } from "next";
import { fetchWithRetries } from "../../lib/apiClient";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  try {
    // simple validation: only allow POST to /do-action
    if (req.method !== "POST") return res.status(405).end();
    const payload = req.body;
    const apiRes = await fetchWithRetries("/do-action", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload),
      useKey: true, // instructs apiClient to add server key
    });
    return res.status(200).json(apiRes);
  } catch (err: any) {
    console.error("proxy error", err);
    return res.status(err?.status || 500).json({ error: String(err?.message || err) });
  }
}

 

  • Prompt — Add a front-end usage example (safe client call)

Create or update src/components/ApiTester.tsx and call the server proxy (so no secret in browser). This UI shows error handling and loading state.

// src/components/ApiTester.tsx
import React, { useState } from "react";

export default function ApiTester() {
  const [loading, setLoading] = useState(false);
  const [result, setResult] = useState<any>(null);
  const [error, setError] = useState<string | null>(null);

  async function run() {
    setLoading(true);
    setError(null);
    try {
      const r = await fetch("/api/proxy", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ input: "test" }),
      });
      const json = await r.json();
      if (!r.ok) throw new Error(json?.error || "Request failed");
      setResult(json);
    } catch (e: any) {
      setError(e.message);
    } finally {
      setLoading(false);
    }
  }

  return (
    <div>
      <button disabled={loading} onClick={run}>{loading ? "Running…" : "Run API"}</button>
      {error && <div style={{color:"red"}}>{error}</div>}
      {result && <pre>{JSON.stringify(result, null, 2)}</pre>}
    </div>
  );
}

 

Operational best-practice notes

 

  • Keep secrets out of client bundles — use Lovable Secrets and server-side routes or external serverless functions.
  • Use Preview to test environment-bound behavior — Preview will surface runtime env differences before Publish.
  • Monitor and retry smartly — implement short timeouts and retry with exponential backoff; return helpful error shapes to the UI.
  • When you need deep control (build hooks, native CLIs, non-Next runtimes) — export/sync to GitHub from Lovable and finish setup/deploy with your normal CI/CD outside Lovable (this is the correct path when a terminal is required).
  • Add small telemetry & circuit-breakers — log failures, track rate-limit responses, and avoid retry storms from the client.


Recognized by the best

Trusted by 600+ businesses globally

From startups to enterprises and everything in between, see for yourself our incredible impact.

RapidDev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with.

They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

Arkady
CPO, Praction
Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost.

He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Donald Muir
Co-Founder, Arc
RapidDev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space.

They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Mat Westergreen-Thorne
Co-CEO, Grantify
RapidDev is an excellent developer for custom-code solutions.

We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Emmanuel Brown
Co-Founder, Church Real Estate Marketplace
Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 

This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Samantha Fekete
Production Manager, Media Production Company
The pSEO strategy executed by RapidDev is clearly driving meaningful results.

Working with RapidDev has delivered measurable, year-over-year growth. Comparing the same period, clicks increased by 129%, impressions grew by 196%, and average position improved by 14.6%. Most importantly, qualified contact form submissions rose 350%, excluding spam.

Appreciation as well to Matt Graham for championing the collaboration!

Michael W. Hammond
Principal Owner, OCD Tech

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.