Connect an External API to Any AI-Built Website or Web App

Connect your app to external data and services securely, without exposing private API keys in the browser.

Roadmap & Resources

Choose What You Want to Connect

Every API connection follows one of two paths, and the API's key decides which. Your AI assistant confirms the right one in Step 2:

Two ways to connect an API

Public API

Browser → API. For APIs with no key, or a key the provider says is safe to show in a browser.

Private API key

Browser → your server → API. The secret key stays on the server and never reaches the browser.

Describe the API Connection

Tell the AI which API you want and what it should do in your app. Never type your API key here or in the AI chat.

Plan Your API Connection

Describe the API and what your app should do with it, and let AI turn it into a clear plan before anything changes.

I want to connect an external API to this existing website or web app. The API or service: {{API_SERVICE}} Its API documentation: {{API_DOCS}} What the app should do with it: {{FEATURE_GOAL}} What users should see or be able to do: {{USER_RESULT}} Where in the app it belongs: {{FEATURE_LOCATION}} My account and API key: {{API_ACCESS}} Do not change any files in this task. This task only plans the connection. Look through the project only enough to use its real names — the actual page, component or feature this belongs to — so the plan describes this app rather than a generic example. Do not audit the code yet. That is the next step. Turn my answers into a short plan with exactly these parts: 1. Service: the API or service, and the part of it this feature uses 2. Feature: what happens in the app, where, and when 3. Likely request: what the app will probably send to the API and ask for, in plain words — not code 4. Expected result: what the user sees, or what happens, after a successful request 5. Key: whether this API probably needs no key, a key that is designed to be public in a browser, or a private key that must stay on a server. This is a first guess — the next step confirms it from the documentation. 6. Still to verify: everything that must be confirmed in the official API documentation before any code is written — the exact endpoint, the method, the required parameters, the authentication and the response fields Rules: - Never invent endpoint names, parameters or response fields. Anything you have not verified in the official documentation goes under Still to verify. - Never ask me to paste an API key or any other secret into this conversation. - If this service looks like it needs something very different from an API key — for example each user signing in to the service with their own account (OAuth), or webhooks that call my app — say so in the plan. - If my answers conflict or leave a gap, ask me instead of guessing. Finish with the plan as a compact list I can copy and keep. Then wait for my approval. Do not implement anything.

Which API or service do you want to use?

OpenWeather

API documentation link (optional)

Paste the link to its API docs

What should your app do with it?

When a user picks a city, show today's weather for it.

What should users see or be able to do?

The temperature, a short description and a weather icon.

Which page or feature should use it?

The city search on the home page

Do you already have an account or API key?

Adjust the plan with the AI until it matches what you want. Keep this conversation open — every later prompt builds on the approved plan. If you ever start a new conversation, paste the plan in first.

Approve the Connection Plan

You should now know what the API will do in your app, and what still needs checking in its documentation.

The plan names the service and the exact feature it powers

It describes the likely request and the result users should see

It lists what still needs verifying in the official API docs

I saved a copy of the final plan

Check the API & Your Project

Inspect the API and Your Project

Nothing changes in this step. The AI checks the real API documentation and your project, then recommends the safest way to connect them.

Check the API & Your Project

Let AI verify the API against its real documentation, map your project, and recommend a public or private connection before anything changes.

Using the connection plan we just approved, check the external API and this project before anything is built. Do not change any files in this task. If the approved plan is not in this conversation, STOP and ask me to paste it. PART 1 — THE PROJECT Find and report: - The framework and build tool, for example React with Vite, or Next.js - Any server-side code the project already has: API routes, server actions, a Node.js server, serverless functions or Supabase Edge Functions - Whether the project uses Supabase, and how: the client, its environment variables and any existing Edge Functions - How environment variables and secrets are handled — names only, never values — and which of them reach the browser, such as VITE_ or NEXT_PUBLIC_ variables - Any existing integration with an outside API, and the pattern it follows, so the new one can reuse it - Where the new feature should live: the page, the component and any shared service or helper - How the project is hosted, if you can tell, and whether that host can run server-side code - Whether a key or secret for this service already appears in frontend code, a browser-exposed variable or a committed file PART 2 — THE API Use the official API documentation — the link in the plan if there is one, otherwise the documentation on the service's own website. Confirm from the documentation itself: - The exact endpoint or endpoints this feature needs - The HTTP method - The required parameters, plus any optional ones this feature genuinely needs - The authentication method — none, an API key, a bearer token or something else — and where it goes, such as a header or a query parameter - The request format, and the response structure with the fields this feature will use - Documented rate limits or usage limits, if they matter here - The important error responses: invalid input, a bad key, a rate limit, a server error - Whether the API accepts calls straight from a browser — some block them - Whether a secret credential is required, or whether the key is designed to be public in a browser — for example a publishable key that can be restricted to your domain Do not invent endpoint names, parameters, headers or response fields. If you cannot open or verify the documentation, say exactly what is missing and what you need from me. Do not guess, and do not fill gaps from memory. If this service needs something fundamentally different from a key — for example each user connecting their own account through OAuth, webhooks that call the app, or enterprise authentication — say so plainly, explain what it means for this project, and recommend the most practical approach. Do not force a simple key-based setup onto a service that does not work that way. PART 3 — THE PATH Recommend exactly one path: - Public API path: the browser calls the API directly. Only when the API needs no key, or its documentation says the key is designed to be public in a browser. No new backend. - Private API key path: the browser calls trusted server-side code, and only that code calls the API with the key. Required whenever the API needs a secret key, a bearer token or any credential that must not be exposed. For the Private API key path, choose where the server-side code runs: - If the project already has suitable server-side code, use it. - If the project uses Supabase, use a Supabase Edge Function, with the key stored in Supabase Edge Function Secrets. - If it has neither, recommend the smallest option that fits how this project is built and hosted — for example a single Supabase Edge Function, which works with any frontend. Explain what I would need to set up, and ask me before adding any new service. If you found a key or secret for this service in frontend code, a browser-exposed variable or a committed file, start your answer with KEY EXPOSED and make moving it to the server part of the plan. Refer to it only by its variable name and file. Never print its value. Return: 1. Existing project architecture 2. API requirements, verified from the documentation — and anything you could not verify 3. Recommended path — Public API or Private API key — and why 4. Files and functions that need changes 5. A concise implementation plan, in order Wait for my approval before changing anything.

If the AI could not open the documentation, paste the docs link or the relevant page into the same conversation, and let it finish the check.

Approve the Integration Plan

Approve it only when every technical detail comes from the documentation, not from a guess.

The endpoint, method, parameters and authentication come from the official docs

It recommends one path — Public API or Private API key — and says why

It says where the new code will live and which files change

It lists anything it could not verify, instead of guessing

If the answer starts with KEY EXPOSED, your key is visible to anyone who opens your site. Keep going — Step 3 moves it to the server and shows you how to replace it.

Prepare the API Connection

Choose Your Connection Path

Pick the path your check recommended in Step 2. Only that path's prompt appears.

Connection path

Public API

No key, or a key made for browsers. Your app calls the API directly — no server needed.

Prepare the Public Connection

Prepare the Public API path from the approved plan: this app's frontend will call the API directly from the browser. If the approved plan is not in this conversation, STOP and ask me for it. First, confirm from the official documentation that this path is safe: - The API needs no key, or its key is designed to be public in a browser - The API accepts calls from a browser If either is not true — or the check reported KEY EXPOSED for a secret key — STOP and tell me to choose the Private API key path instead. Never put a secret key in frontend code to make this path work. Then prepare the connection, without building the request yet: - Create or reuse one small frontend helper for this API, following the project's existing pattern for outside services if it has one - If the API uses a public key, read it from a browser-safe environment variable that follows this framework's naming rule, such as VITE_ for Vite. Never hardcode it. - If the project has an example environment file, add the variable's name there without a value - Do not create a backend, a server route or an Edge Function. This path does not need one. Give me: 1. What you created or changed, and where 2. The variable name I need to set, if any, and every place it must be set — my local environment file, plus my hosting's build settings if the site is built there 3. Whether the provider lets me restrict the key, for example to my website's domains, and where in its dashboard, from its documentation Do not call the API yet — the request is built in the next step.

Private API key

A secret key. Your server calls the API with it, and the key never reaches the browser.

Prepare the Private Connection

Prepare the Private API key path from the approved plan: the browser will call trusted server-side code, and only that code will call the API with the key. If the approved plan is not in this conversation, STOP and ask me for it. Use the server-side location the plan chose: - Existing server-side code: add the new endpoint there, following its existing patterns - Supabase: create one Supabase Edge Function with a clear name that says what it does, such as get-weather - Neither: set up only the option I approved in the plan, and nothing bigger Prepare it, without building the real request yet: - Read the API key on the server only, from one secret with a clear name, such as WEATHER_API_KEY. For a Supabase Edge Function, that is a Supabase Edge Function Secret read with Deno.env.get. - If the secret is missing, return a clear error that names the missing setting, never a value - Handle the browser's CORS preflight the way the platform's current documentation shows. If you limit which websites may call it, include both my local address and my live domain. - For local testing, read the key from a local environment file that Git ignores — for a Supabase Edge Function, supabase/functions/.env. Check that the file is ignored before anything goes into it. Never: - Put the key in frontend code, or in a browser-exposed variable such as VITE_ or NEXT_PUBLIC_ - Return the key to the browser, or print it in full in any log - Commit it to Git, or store it in localStorage - Use a Supabase Secret or service-role key in browser code If the check reported KEY EXPOSED: - Remove the exposed key from every file and variable that reaches the browser, and from committed files - Tell me plainly that the old key must be treated as leaked and replaced at the provider, and that the old browser call stops working until the app is connected to the new server endpoint in a later step Give me: 1. What you created or changed, and where 2. The exact secret name I need to add, and where to add it for local testing and for the live app 3. The endpoint or function the app will call Do not call the external API yet — the request is built in the next step.

Run the prompt in the same AI conversation Read what the AI prepared Note the exact name of any key it asks you to add — you need it in the next task

Expected result

The AI has prepared one place for the API call — in the frontend for a public API, on the server for a private key — and told you the exact name of any key it needs.

Add Your API Key Safely

This follows the path you chose above. The key goes in one place only, under the exact name the AI gave you.

No key? There is nothing to add — go straight to the next step. If your API uses a public key:

Create or copy the key your provider marks as safe for browsers — often called a publishable, public or client key Restrict it to your website's domains in the provider's dashboard, if it offers that Add it to your local environment file under the exact name the AI gave you Add the same variable to your hosting's build settings, if your site is built there

A public key is visible to anyone who opens your site — that is how it is designed. Restricting it to your domains keeps others from reusing it.

Add the key where only your server can read it:

Create or copy the API key in your provider's dashboard Open your server's secret settings — for a Supabase Edge Function, that is the Secrets page below Add the key under the exact name the AI gave you, then save For local testing, add it only to the local file the AI named — never to a file that gets committed

Edge Functions Secrets

Supabase project

Using a different backend? Add the key to its server-side environment variables instead.

Keep the key off the browser

Never put a private key in frontend code, a VITE_ or NEXT_PUBLIC_ variable, a commit or the AI chat. Anything that reaches the browser can be copied by anyone who opens your site.

Key already exposed? Replace it

If the check reported KEY EXPOSED, treat that key as leaked. Create a new key now and store only the new one here. Delete the old key at your provider as soon as the fixed version is live — right away if you see usage you don't recognize.

Expected result

The app now has the correct secure place from which to call the external API.

Build the API Request

Build the Request

The AI builds the real call to the API, using only what the documentation confirms.

Build the API Request

Build the real API request with verified settings, safe input checks, clear errors and a timeout — then get one direct test before any page depends on it.

Now build the real request to the external API, following the approved plan and the connection we just prepared. The connection path is: {{selection:apiPath|Not chosen in the guide — use the path from the approved plan, and ask me if it is unclear.}} If the approved plan is not in this conversation, STOP and ask me for it. For both paths: - Use the exact endpoint, HTTP method, headers, authentication and parameters confirmed in the official documentation. Never invent or guess one. - Send only the parameters this feature needs — no app data or personal data the API does not need - Parse the response and keep only the fields this feature uses. Never pass a large provider response through when the app needs a few values. - Stop a request that takes too long — for example after 10 seconds — with the timeout support this runtime provides, so the app never waits forever Private API key path — the browser calls the server endpoint, and only the server calls the API: - Add the API key on the server, from the secret we set up. Never send it to the browser. - Validate what the browser sends before calling the API: required fields, types, lengths and allowed values - The server decides which API and which endpoint it calls. Never accept a URL, an endpoint, headers or free-form API parameters from the browser, and never forward a request as it arrived — this endpoint must not become an open proxy. - If the feature is only for signed-in users, verify the user on the server before the API call, using the platform's current recommended method. For a Supabase Edge Function, follow the current Supabase docs for verifying the caller rather than guessing. Reject everyone else before any API call happens. - If the feature is meant to be public, do not add sign-in just for this. Keep every other protection above. - Return only the fields the frontend needs Public API path — the browser calls the API directly: - Build the request in the frontend helper we prepared, reading any public key from its browser-safe variable - Validate the user's input before sending it Errors, for both paths — turn each into a short, useful message for the app: - Invalid request or missing input - Unauthorized request or a problem with the API key - Rate limit reached — never retry in a loop - Timeout - Provider or server error - A response that is unexpected or incomplete Never show the app a secret, a stack trace, internal server details or the raw provider error. Log enough on the server to debug a failure, without secrets or personal data. Then give me ONE way to test the request directly, before any UI uses it: - Private API key path: one call to the endpoint with a realistic test input — a single command I can run, or the function's test panel in the Supabase Dashboard. If the endpoint needs a signed-in user, give me the simplest safe way to test it as a test user, never with a Supabase secret or service-role key. - Public API path: one request with a realistic test input that I can run and read Tell me exactly what a successful response should look like. Deploy the Edge Function if this path uses one, and run the project's build afterwards.

Expected result

The request is built, and the AI has given you one direct test and told you what a successful response looks like.

See One Real Response

Prove the request works with real data before any page depends on it.

Run the direct test the AI gave you Check the response holds real data from the API — not sample or placeholder values Check it contains only the fields your feature needs, and never a key Test once more with a missing or invalid input

If a result is not what the AI described, paste it into the same conversation and let the AI fix the request before you continue.

Expected result

You have seen one real, successful response from the API — and a clear error, not a crash, for the bad input.

Connect the API to Your Web App

Connect the Feature

Add the working request to the real page, in your app's existing design.

Connect the API to Your App

Add the feature to your real page with loading, success, empty and error states — in your existing design, without exposing any key.

Now connect the working API request to the real feature in this app, following the approved plan. The connection path is: {{selection:apiPath|Not chosen in the guide — use the path from the approved plan, and ask me if it is unclear.}} If the approved plan is not in this conversation, STOP and ask me for it. Inspect the page, its components and the app's existing design first. Preserve the design, and add only what this feature needs. What should start the request: {{UI_TRIGGER}} How the result should appear: {{RESULT_DISPLAY}} Saving the results: {{SAVE_RESULTS}} Anything else to include or leave out: {{EXTRA_REQUESTS}} Build: - Only the inputs and the result this feature needs, with the app's existing components and styles - Idle: what the feature shows before anything is requested - Loading: a clear loading state while the request runs - Success: the real result from the API, shown the way the plan describes - Empty: a short, helpful message when the API returns nothing useful, where that can happen - Error: the useful message from the request step, with a way to try again. Never a blank screen, a raw error or a stack trace. - No duplicate requests: while a request is running, disable the trigger or ignore repeats, so one action sends one request Keys: - Private API key path: the frontend calls only our server endpoint — never the external API directly — and never receives, stores or logs the key - Public API path: the frontend uses the helper we built, with only the public key the provider allows Saving: - Save results only as my saving choice above says. Never save every API response by default. - If results are saved in Supabase, store only the fields the app needs. Records that belong to a user must be protected with Row Level Security, so each user can reach only their own. Give me the SQL in ONE block that is safe to run again, and save it as a migration if the project keeps them. Caching: - Do not add caching by default. Only if this API is expensive or strictly rate-limited, and the same result is requested again and again, recommend one small caching approach that fits this project — and ask me before building it. When you are done, list the files you changed and where the feature now appears. Run the project's build afterwards.

What should start the request?

How should the result appear?

A small card under the search box

Should the app save the results?

Anything to include or leave out?

Show the temperature in Celsius, and hide the card until a city is chosen.

Expected result

The feature works on the real page: it shows a loading state, then the real result from the API — and a clear message when something goes wrong.

Try Every State

Use the feature once the way a real user would, including one mistake.

Before any request, the feature shows its starting state

A loading state appears while the request runs

The real result appears where the plan said

A missing or invalid input shows a helpful message, not a crash

Repeating the action quickly does not send duplicate requests

The rest of the page still works

Test the Complete Integration

Run the Full Integration Check

The AI checks the whole integration — the real result, every failure case and every security boundary — before you rely on it.

Test the Complete Integration

Verify the real result, errors, rate limits, production settings and every security boundary — including that no private key ever reaches the browser.

Help me verify the complete API integration before I rely on it. Test what you can yourself, tell me exactly what to check by hand, and fix only what is broken. The connection path is: {{selection:apiPath|Not chosen in the guide — use the path from the approved plan, and ask me if it is unclear.}} If the approved plan is not in this conversation, STOP and ask me for it. Check each item below. Mark any that does not apply to this integration as NOT APPLICABLE, and say why. 1. Real result: the external API returns the expected result for a realistic input 2. Display: the app shows or uses that result correctly 3. Loading: the loading state appears while a request runs 4. Invalid input: a missing or invalid input is rejected with a clear message — before any API call, where possible 5. Provider errors: an API error, such as a bad key or a server error, produces a useful message in the app, not a crash. Prove it by reading the code or with a safe local simulation — never by breaking my live key. 6. Rate limits: a rate-limit response is handled gracefully, with no retry loop. Check the code, or simulate it locally where practical. 7. Refresh: reloading the page does not break the feature 8. Production key: the live app reads the right key from the right place — Supabase Edge Function Secrets, the backend's server-side variables, or the host's build settings for a public key. If the app is not live yet, tell me exactly what to set before publishing. 9. Browser code: no private key appears in frontend source, a browser-exposed variable or the production build output. Search them for the secret's variable name and for anything that looks like the key. Never print a key if you find one. 10. Responses: the endpoint's responses never contain the key 11. Logs: the key is never printed, in the browser console or in server logs 12. No open proxy: the endpoint rejects any request that tries to change the URL, the endpoint, the headers or the API parameters it sends 13. Sign-in: if the feature requires sign-in, a request with no session or an invalid one is rejected before the API is called 14. Saved data: if results are saved per user, one user cannot read another user's saved results — test with two accounts 15. Existing features: the rest of the app still works as before 16. Live domain: the feature works on the live domain — the endpoint accepts calls from the live site, and any key restrictions include the live domain. If the app is not live yet, tell me what to check once it is. Repeated use: if this API costs money per request, confirm that fast repeated clicks or submissions cannot trigger a burst of duplicate calls. This is a basic check — full usage limits are a separate job. Use test inputs only. Do not change real users' data, and keep real API calls to the few the checks need. Report expected versus actual for every item, then finish with exactly one verdict: INTEGRATION READY or NEEDS ATTENTION If NEEDS ATTENTION, list only what is still failing.

Continue when the AI reports INTEGRATION READY. If it reports NEEDS ATTENTION, fix the listed issues and run the check again.

Check the Live App

Publish the update the way you normally do, then use the feature on your live site like a real user.

Publish the updated app the way you normally do Open your live site and use the feature once Refresh the page and use it again

Then search the live site for your key: open your browser's developer tools, press Ctrl+Shift+F (Cmd+Option+F on a Mac) and search for the first few characters of your private key.

The feature works on the live site with real data from the API

It still works after a refresh

Searching the live site's files finds no trace of my private key

If my old key was exposed, I deleted it at the provider

My public key is restricted to my domains, if my provider offers that

The rest of my site works as before

Your web app is now connected to the external API, with the integration working securely without exposing private credentials.