# How to Integrate Lovable with Bandwidth

- Tool: Lovable
- Difficulty: Intermediate
- Time required: 45 minutes
- Last updated: March 2026

## TL;DR

To integrate Lovable with Bandwidth, create a Supabase Edge Function that proxies Bandwidth API calls using your API Token and Secret. Store credentials in Cloud → Secrets, then build Edge Functions to send SMS, make voice calls, and receive inbound message webhooks. Bandwidth is an enterprise CPaaS with direct carrier connections — its API is best suited for high-volume or mission-critical communication workflows.

## Enterprise voice and messaging in Lovable with Bandwidth's direct carrier API

Bandwidth operates its own nationwide voice and messaging network rather than reselling carrier services, which is what distinguishes it from other CPaaS providers. This direct carrier model gives Bandwidth advantages in regulatory compliance (particularly for 911/emergency services), throughput at scale, and latency — making it the choice for enterprises in healthcare, financial services, and public safety where carrier-grade reliability is non-negotiable. The trade-off is that Bandwidth has historically targeted enterprise buyers rather than individual developers, so setup involves account configuration that is more involved than Twilio or Sinch.

In Lovable, Bandwidth calls are made from a server-side Edge Function using HTTP Basic Auth with your API Token and Secret. The Messaging API v2 endpoint accepts JSON bodies specifying the from number (one of your purchased Bandwidth numbers), to number, text content, and account/application identifiers. Voice calls use a different endpoint and a BXML (Bandwidth XML) response format similar to TwiML. Both services are proxied through your Edge Function, keeping your credentials secure in Cloud → Secrets.

This guide focuses on the Messaging API v2 — the current production API for SMS and MMS — with a secondary section on receiving inbound message callbacks. If you need voice call integration or 911 emergency calling, the patterns are similar but require additional Bandwidth account configuration for BXML hosting and emergency address registration.

## Before you start

- A Lovable project with Lovable Cloud enabled (verify via the Cloud tab in the editor)
- A Bandwidth account with API access at dashboard.bandwidth.com — enterprise accounts are provisioned by Bandwidth sales
- A Bandwidth phone number purchased and configured with a Messaging Application in the Bandwidth Dashboard
- Your Bandwidth Account ID, API Token, and API Secret from the dashboard
- Familiarity with Lovable's Edge Function pattern — all authenticated API calls go through server-side functions

## Step-by-step guide

### 1. Locate your Bandwidth credentials in the dashboard

Sign in to the Bandwidth Dashboard at dashboard.bandwidth.com. Your Account ID is displayed prominently at the top of the main dashboard page — it is a numeric identifier like 12345678. Next, navigate to 'Account' → 'API Credentials' in the left sidebar. Here you will find your API Token (username) and API Secret (password). These are used together for HTTP Basic Auth on all Bandwidth API v2 requests.

You also need to note your Messaging Application ID. Go to 'Applications' in the left sidebar and find or create a Messaging Application — this is a Bandwidth configuration entity that links your phone numbers to a callback URL. The Application ID is a UUID like a1b2c3d4-e5f6-7890-abcd-ef1234567890. If you do not have an application yet, create one now and associate your purchased Bandwidth phone number to it. The callback URL will be your inbound webhook Edge Function URL, which you will configure in a later step.

**Expected result:** Account ID, API Token, API Secret, and Messaging Application ID copied and ready to store in Lovable's Secrets panel.

### 2. Store Bandwidth credentials in Cloud → Secrets

In your Lovable editor, click the '+' icon near the top-right to open the panel selector, then choose the Cloud tab. Scroll to the 'Secrets' section and add four secrets by clicking the '+' button next to Secrets for each one.

Name the first secret BANDWIDTH_ACCOUNT_ID and paste your numeric Account ID. Name the second BANDWIDTH_API_TOKEN and paste your API Token. Name the third BANDWIDTH_API_SECRET and paste your API Secret. Name the fourth BANDWIDTH_APPLICATION_ID and paste your Messaging Application ID. Name the fifth BANDWIDTH_FROM_NUMBER and paste your Bandwidth phone number in E.164 format (e.g. +12025551234).

Secret names must match exactly what your Edge Function will call with Deno.env.get(). Bandwidth uses Basic Auth where the username is the API Token and the password is the API Secret — both are required. Lovable's security layer encrypts all secrets at rest and prevents them from appearing in generated code. The platform actively blocks approximately 1,200 hardcoded API keys per day, so always use the Secrets panel rather than pasting credentials into chat prompts or code fields.

**Expected result:** Five secrets (BANDWIDTH_ACCOUNT_ID, BANDWIDTH_API_TOKEN, BANDWIDTH_API_SECRET, BANDWIDTH_APPLICATION_ID, BANDWIDTH_FROM_NUMBER) saved in Cloud → Secrets.

### 3. Build the SMS sending Edge Function

Use the Lovable chat to generate the SMS Edge Function. The function must construct an HTTP Basic Auth header from the API Token and Secret (using btoa), then POST to Bandwidth's messaging endpoint at https://messaging.bandwidth.com/api/v2/users/{accountId}/messages. The request body is JSON with applicationId, to (array of destination numbers), from (your Bandwidth number), and text.

Bandwidth's Messaging API v2 returns a 202 Accepted status on success (not 200), with a response body containing the message ID. Your Edge Function should parse this and return the messageId to your Lovable frontend. For MMS, add media (array of URLs) and omit the text field or include both. The API supports up to 10 recipient numbers per request for group messaging, though each number is billed separately.

After Lovable deploys the function, test it from the Lovable chat by asking it to add a simple test trigger, or verify in Cloud → Logs that the function is deploying without errors.

```
// supabase/functions/bandwidth-sms/index.ts
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';

const corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};

serve(async (req) => {
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders });
  }

  try {
    const accountId = Deno.env.get('BANDWIDTH_ACCOUNT_ID')!;
    const apiToken = Deno.env.get('BANDWIDTH_API_TOKEN')!;
    const apiSecret = Deno.env.get('BANDWIDTH_API_SECRET')!;
    const applicationId = Deno.env.get('BANDWIDTH_APPLICATION_ID')!;
    const fromNumber = Deno.env.get('BANDWIDTH_FROM_NUMBER')!;

    const { to, text } = await req.json();

    const credentials = btoa(`${apiToken}:${apiSecret}`);

    const response = await fetch(
      `https://messaging.bandwidth.com/api/v2/users/${accountId}/messages`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Basic ${credentials}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          applicationId,
          to: [to],
          from: fromNumber,
          text,
        }),
      }
    );

    // Bandwidth returns 202 on success
    if (response.status !== 202 && !response.ok) {
      const error = await response.text();
      throw new Error(`Bandwidth API error ${response.status}: ${error}`);
    }

    const data = await response.json();

    return new Response(
      JSON.stringify({ messageId: data.id, status: 'queued' }),
      { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    );
  } catch (error) {
    return new Response(
      JSON.stringify({ error: error.message }),
      { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    );
  }
});
```

**Expected result:** A deployed bandwidth-sms Edge Function that sends SMS messages via the Bandwidth API and returns a message ID.

### 4. Handle inbound SMS callbacks from Bandwidth

When someone replies to your Bandwidth number or sends an inbound SMS, Bandwidth posts a JSON callback to the URL you configured in your Messaging Application. You need a second Edge Function to receive these callbacks, validate they are from Bandwidth, and store the inbound messages in your Supabase database.

Create a second Edge Function called bandwidth-inbound. This function receives POST requests from Bandwidth with a JSON array of message event objects. Each event contains type (message-received), message.id, message.from, message.to, message.text, and message.time. Parse the array, extract the relevant fields, and insert a row into your Supabase database using the service role key for server-side writes.

After deploying the Edge Function, copy its URL from Cloud → Edge Functions. Go back to Bandwidth Dashboard → Applications → your Messaging Application, and paste the Edge Function URL as the 'Inbound Message Callback' URL. Set the callback method to POST. Bandwidth will now forward all inbound SMS events to your Edge Function. Test by sending a text message to your Bandwidth number from any phone.

**Expected result:** An inbound SMS callback Edge Function deployed and registered in Bandwidth Dashboard, storing incoming messages in your Supabase database.

## Best practices

- Store all five Bandwidth credentials (Account ID, API Token, API Secret, Application ID, From Number) as separate Secrets for easy rotation and environment switching
- Always use E.164 format for phone numbers (+12025551234) — Bandwidth's API rejects national or local formats
- Check the Bandwidth Message Logs in the dashboard first when debugging delivery failures — they show detailed delivery status codes
- Return HTTP 200 from your inbound callback Edge Function immediately and process events asynchronously to avoid Bandwidth retry storms
- For 10DLC compliance, register your brand and campaign in the Bandwidth Dashboard before sending application-to-person marketing or transactional messages at scale
- Use separate Bandwidth Messaging Applications for development and production, each with different callback URLs pointing to your respective Edge Function environments
- Log the Bandwidth message ID returned by the API in your Supabase database — it is the key for looking up delivery status in Message Logs

## Use cases

### High-volume SMS notification system for enterprise clients

Send transactional SMS notifications — appointment reminders, order updates, fraud alerts — to customers at enterprise scale. Bandwidth's direct carrier connections improve deliverability for high-volume senders and reduce the risk of messages being flagged as spam compared to aggregator-based providers.

Prompt example:

```
Create an SMS notification system that calls my bandwidth-sms Edge Function to send appointment reminder messages. Add a Supabase table called sms_logs to track message ID, recipient, status, and timestamp. Show a send history table in the admin dashboard.
```

### Two-way SMS customer support chat

Build an SMS-based support channel where your team can send and receive messages from customers. Inbound messages hit your Bandwidth callback Edge Function, get stored in Supabase, and appear in a real-time chat interface in Lovable built with Supabase Realtime subscriptions.

Prompt example:

```
Build a two-way SMS support interface. Outbound messages go through my bandwidth-sms Edge Function. Inbound messages come in through my bandwidth-inbound Edge Function and get stored in a conversations table. Show a real-time chat thread grouped by phone number using Supabase Realtime.
```

### Programmable voice call launcher for sales teams

Create a click-to-call feature in a Lovable CRM where sales reps can initiate outbound calls to leads. The Edge Function triggers a Bandwidth voice call and stores call logs. Call recordings and outcomes can be synced back via Bandwidth's call status callbacks.

Prompt example:

```
Add a click-to-call button to each contact record in my CRM. When clicked, call my bandwidth-voice Edge Function to initiate an outbound call from our Bandwidth number to the contact's phone. Log the call_id, contact_id, and timestamp in a call_logs table.
```

## Troubleshooting

### Edge Function returns 401 Unauthorized when calling the Bandwidth API

Cause: The HTTP Basic Auth header is incorrectly constructed, or the API Token and Secret values in Cloud → Secrets contain extra whitespace or are swapped.

Solution: Verify the exact values in Cloud → Secrets — the API Token is the username and the API Secret is the password in the Basic Auth scheme. The btoa encoding must be btoa(token + ':' + secret) with a colon separator. Open Cloud → Logs to see the raw error response from Bandwidth for more detail.

```
const credentials = btoa(`${Deno.env.get('BANDWIDTH_API_TOKEN')}:${Deno.env.get('BANDWIDTH_API_SECRET')}`);
```

### Bandwidth API returns 403 Forbidden with error mentioning the Application ID

Cause: The phone number is not associated with the Messaging Application ID stored in your secrets, or the Application ID is incorrect.

Solution: Log in to Bandwidth Dashboard → Applications and verify your Messaging Application ID (UUID format). Then check the phone number is associated with this application under 'Numbers'. If the number is associated with a different application, either update the BANDWIDTH_APPLICATION_ID secret or reassign the number.

### SMS messages send successfully (202 returned) but recipients never receive them

Cause: The destination number may be in a format Bandwidth cannot route, or the Bandwidth account needs to be enabled for 10DLC registration for application-to-person messaging.

Solution: Ensure destination numbers are in E.164 format (+1XXXXXXXXXX for US numbers). Check Bandwidth Dashboard → Message Logs for delivery status. If messages show as 'undeliverable', your account may require 10DLC brand and campaign registration for A2P messaging compliance — contact Bandwidth support to check your account's registration status.

### Bandwidth inbound callback never fires even after sending a test SMS to the Bandwidth number

Cause: The callback URL in the Messaging Application is pointing to the wrong Edge Function URL, or the Lovable app is not published and the Edge Function URL is not publicly accessible.

Solution: In Bandwidth Dashboard → Applications → your app, verify the Inbound Message Callback URL exactly matches your deployed Edge Function URL (from Cloud tab → Edge Functions list). The URL must be HTTPS and publicly reachable. Note that Lovable preview URLs are not suitable for webhooks — use the deployed production Edge Function URL.

## Frequently asked questions

### Is Bandwidth suitable for startups or is it only for enterprise?

Bandwidth primarily targets enterprise customers and requires an account provisioning process. Pricing is custom and typically volume-based rather than pay-per-message at the developer tier. For startups or small-volume SMS needs, Twilio or Plivo will be easier to set up and more cost-effective.

### Does Bandwidth support WhatsApp or RCS messaging?

Bandwidth's primary messaging products are SMS and MMS over its own carrier network. It does not offer WhatsApp Business API access through its platform. For multi-channel messaging including WhatsApp, consider Sinch or Twilio, which have dedicated Conversation API products supporting WhatsApp, RCS, and other channels.

### How does Bandwidth's 911 service integration work with Lovable apps?

Bandwidth's 911 service is a separate enterprise product requiring dedicated account setup, E911 provisioning, and address registration. It is not something you configure through a standard API integration — it requires direct coordination with Bandwidth's enterprise team. This feature is most relevant for UCaaS platforms and public safety applications rather than typical Lovable projects.

### Can I receive voice call audio recordings via a Lovable Edge Function?

Yes — Bandwidth's Voice API uses BXML (Bandwidth XML) to control call flows, and you can include a Record verb in your BXML to record calls. Bandwidth posts a callback to your Edge Function with a recording URL when the call ends. Your Edge Function can then download and store the recording in Supabase Storage. This requires a separate voice-focused Edge Function that returns BXML responses, which is a more complex integration than SMS.

---

Source: https://www.rapidevelopers.com/lovable-integration/bandwidth
© RapidDev — https://www.rapidevelopers.com/lovable-integration/bandwidth
