AI-generated app with a Supabase backend
WhatsApp in Lovable: Supabase Edge Function, Secrets and the right prompt
Lovable generates apps from a conversation and, with the Supabase integration, uses a project of yours as the backend, including edge functions (server functions). According to its documentation (read on 2026-11-11), calling external APIs with secret keys is a typical use of edge functions, and secrets are kept in Supabase, outside the app's code. That is exactly where the ZapZap key belongs.
Updated on
Why connect
You describe the product (a scheduler, a lead CRM, an orders portal) and Lovable builds the screen. What it should not do is call the WhatsApp API straight from the browser, because the key would be exposed. The fix is an edge function that takes the request from the app and talks to ZapZap. ZapZap connects numbers through an unofficial channel: WhatsApp may limit or block any number, so pacing, consent and warm-up matter. It costs R$15 per active number per month, prepaid, with no per-message fee, and you start with a welcome credit when you verify your phone, subject to the current campaign.
Step by step
- 1
Connect Supabase to the project
In Lovable's documentation, the Supabase integration links a project of yours as the backend and allows edge function deploys. Connect it before asking for any WhatsApp sending.
- 2
Add the three secrets
In More > Settings > Secrets (or when Lovable asks through the secure field in the chat), create ZAPZAP_API_KEY, ZAPZAP_API_SECRET and ZAPZAP_INSTANCE_ID. The documentation says secrets are injected into edge functions at runtime and never reach the frontend code or the browser. The keys come from Settings > API at app.zapzapapi.com.
- 3
Ask for the function with a closed prompt
Example: "Create an edge function send-whatsapp that receives number and text, validates a number with 10 to 15 digits and calls POST https://api.zapzapapi.com/api/v1/{instanceId}/send/text with the x-api-key and x-api-secret headers read from the secrets. Do not use the key in the frontend." Paste the example code as a reference.
- 4
Call the function from the app, with an authenticated user
In the frontend, the app uses the Supabase client to invoke send-whatsapp. Require login first: an open function that sends messages becomes a spam channel on your number. Limit text size and frequency per user.
- 5
Receive messages with another edge function
Create a second function and register its URL with PUT /instances/{id}/webhook (webhook_url and events). ZapZap returns the instance's whsec_ secret: store it as a secret and validate the X-ZapZap-Signature header (t=<unix>,v1=<hmac_hex>, HMAC-SHA256 over t + dot + raw body, 5-minute tolerance).
- 6
Test with your own number
Before you go live with customers, send to yourself, check the HTTP response and look at the function log. Use GET /{instanceId}/instance/status to see whether the instance is connected.
Example
// Supabase Edge Function (Deno): supabase/functions/send-whatsapp/index.ts
// Secrets: ZAPZAP_API_KEY, ZAPZAP_API_SECRET, ZAPZAP_INSTANCE_ID (never in the frontend)
const cors = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
};
Deno.serve(async (req: Request) => {
if (req.method === "OPTIONS") return new Response("ok", { headers: cors });
const { number, text } = await req.json();
if (!/^\d{10,15}$/.test(String(number)) || !text) {
return new Response(JSON.stringify({ error: "invalid number or text" }), { status: 400, headers: cors });
}
const r = await fetch("https://api.zapzapapi.com/api/v1/" + Deno.env.get("ZAPZAP_INSTANCE_ID") + "/send/text", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": Deno.env.get("ZAPZAP_API_KEY") ?? "",
"x-api-secret": Deno.env.get("ZAPZAP_API_SECRET") ?? "",
},
body: JSON.stringify({ number, text }),
});
return new Response(await r.text(), { status: r.status, headers: { ...cors, "Content-Type": "application/json" } });
});Illustrative. The exact fields and endpoints are in the documentation.
What Lovable solves and what stays with you
| Part | Who does it | Note |
|---|---|---|
| App screen and flow | Lovable | From your prompt |
| Edge function and secrets | Lovable + Supabase | Secrets live in Supabase, not in the code (documentation read on 2026-11-11) |
| Connecting the number by QR code | You, in the ZapZap dashboard | Once per number |
| Pacing, consent and warm-up | You | See the chip warm-up guide |
Frequently asked questions
Can I call ZapZap straight from Lovable's frontend?
You should not. The key and secret would give full access to your number if they sat in the browser. Use an edge function and keep the keys in Secrets.
Where do the secrets live?
In your Supabase project. Lovable's documentation (read on 2026-11-11) says they do not appear in the code or the repository and are injected into edge functions at runtime.
Does Lovable write the function by itself?
It writes and deploys the function from your description. Review the generated code: check that it uses the secrets, validates the number and requires an authenticated user.
How do I receive customer replies?
With a webhook pointing to another edge function. Validate the X-ZapZap-Signature and use delivery_id to ignore repeated deliveries.
What does it cost?
It costs R$15 per active number per month, prepaid, with no per-message fee, and you start with a welcome credit when you verify your phone, subject to the current campaign.
Start now
Create your account, connect a number in minutes and test the API with warm-up and anti-ban. R$15 per active number/month, prepaid, no lock-in.
