# How to Integrate Bolt.new with Twilio

- Tool: Bolt.new
- Difficulty: Intermediate
- Time required: 20 minutes
- Last updated: April 2026

## TL;DR

To integrate Twilio with Bolt.new, install the twilio npm package (works in WebContainers) and create a Next.js API route that sends SMS using your Account SID and Auth Token from .env. Outbound SMS sending works in the Bolt preview. Incoming SMS webhooks and voice call receiving require a deployed URL — test outbound during development, then deploy to Netlify or Bolt Cloud to test incoming messages and webhooks.

## Adding SMS, Voice, and WhatsApp to Bolt.new Apps with Twilio

Twilio is the leading communications API platform, powering SMS notifications, phone number verification, WhatsApp messaging, and voice calls for millions of applications. The Twilio Node.js SDK installs and runs in Bolt's WebContainer without issues — it's pure JavaScript that communicates with Twilio's REST API over HTTPS, perfectly compatible with the WebContainer's networking model.

The key distinction for Bolt development is between outbound and inbound communications. Outbound operations — sending an SMS, initiating a phone call, sending a WhatsApp message — work completely in the Bolt preview. Your API route makes an HTTPS call to Twilio's API, and Twilio handles the delivery to the end recipient. You can test these fully during development without deploying. Inbound operations — receiving an SMS, answering a voice call — require Twilio to call a webhook URL on your server when the message or call arrives. Since Bolt's WebContainer has no public URL (it runs inside a browser tab), Twilio cannot deliver these webhook events during development. Deploy to Netlify or Bolt Cloud first, then configure your Twilio phone number's webhook URL to point to your deployed endpoint.

Twilio Verify is worth highlighting as a separate use case. It provides a managed OTP (one-time password) service for phone number verification — the kind of '6-digit code sent to your phone' flow used in signup and 2FA. Twilio handles the code generation, rate limiting, fraud prevention, and expiry. The sending step works in Bolt's preview; the verification step (checking the code the user entered) is purely server-side and works in both dev and production.

## Before you start

- A Twilio account (free trial includes $15.50 credit, enough for hundreds of test messages)
- A Twilio phone number purchased or trial number from the Twilio Console
- Your Twilio Account SID and Auth Token from the Twilio Console dashboard
- A Bolt.new project using Next.js for server-side API routes
- For Twilio Verify: a Verify Service SID created in the Twilio Console under Verify → Services

## Step-by-step guide

### 1. Get Twilio Credentials and Configure a Phone Number

Your Twilio integration requires three pieces of information from the Twilio Console: your Account SID (a 34-character string starting with 'AC'), your Auth Token (another 34-character string), and a Twilio phone number that can send SMS. Log into console.twilio.com. On the main dashboard page, your Account SID and Auth Token are displayed (click the eye icon to reveal the Auth Token). Copy both. Next, get a phone number: in the left sidebar, navigate to Phone Numbers → Manage → Buy a Number. Filter by SMS capability and choose a number in your country. Trial accounts get one free number and can only send to verified phone numbers (add your personal number under Phone Numbers → Verified Caller IDs for testing). For Twilio Verify (OTP), go to Verify → Services → Create Service. Give it a name like 'MyApp Verification' and copy the Service SID (starts with 'VA') shown after creation.

**Expected result:** You have your Account SID (AC...), Auth Token, a Twilio phone number in E.164 format (+1XXXXXXXXXX), and optionally a Verify Service SID (VA...) all saved for the next step.

### 2. Install Twilio SDK and Configure Environment Variables

The twilio npm package is the official Node.js helper library. It's pure JavaScript and works cleanly in Bolt's WebContainer runtime. Prompt Bolt to install it and set up the environment variable structure. Twilio credentials must only be accessed server-side — never in client components. Your Account SID and Auth Token give full control over your Twilio account including sending messages and making calls to any number. In a Next.js project, server-side environment variables (without NEXT_PUBLIC_) are only readable in API routes and server components. The phone number can also be stored as an environment variable so you can change it without touching code — useful when moving from a trial number to a production number.

```
# .env
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=your_auth_token_here
TWILIO_PHONE_NUMBER=+15551234567
TWILIO_VERIFY_SERVICE_SID=VAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

**Expected result:** The twilio package is in package.json. The .env file has your real Twilio credentials. lib/twilio.ts exports an initialized Twilio REST client.

### 3. Create the SMS Sending API Route

The SMS API route is the core of your Twilio integration. It receives a phone number and message from your frontend, validates the input, then uses the Twilio client to send the SMS. The route runs server-side in Bolt's WebContainer Node.js process, so it can access environment variables and make outbound HTTPS calls to Twilio's API without CORS restrictions. This outbound SMS sending works fully in the Bolt preview — you can test it immediately without deploying. Important: always validate phone number format before passing to Twilio. Numbers must be in E.164 format (+[country code][number], e.g., +14155552671). The Twilio SDK throws an error if the format is invalid, so a simple regex validation in the route prevents unhelpful error messages.

```
import twilio from 'twilio';
import { NextResponse } from 'next/server';

const client = twilio(
  process.env.TWILIO_ACCOUNT_SID,
  process.env.TWILIO_AUTH_TOKEN
);

const E164_REGEX = /^\+[1-9]\d{1,14}$/;

export async function POST(request: Request) {
  try {
    const { to, message } = await request.json();

    if (!to || !E164_REGEX.test(to)) {
      return NextResponse.json(
        { error: 'Invalid phone number. Use E.164 format: +14155552671' },
        { status: 400 }
      );
    }

    if (!message || message.trim().length === 0) {
      return NextResponse.json(
        { error: 'Message cannot be empty' },
        { status: 400 }
      );
    }

    const msg = await client.messages.create({
      body: message,
      from: process.env.TWILIO_PHONE_NUMBER!,
      to,
    });

    return NextResponse.json({ success: true, messageSid: msg.sid });
  } catch (error: unknown) {
    const twilioError = error as { message: string; code?: number };
    return NextResponse.json(
      { error: twilioError.message, code: twilioError.code },
      { status: 500 }
    );
  }
}
```

**Expected result:** POST to /api/twilio/send-sms with a valid phone number and message sends an actual SMS to that number. The response includes a messageSid for tracking delivery status.

### 4. Add Twilio Verify for OTP Authentication

Twilio Verify provides a managed OTP service that handles the complexity of phone verification: generating secure codes, managing expiry (10 minutes by default), rate limiting (5 attempts per verification), and supporting both SMS and voice delivery. Using Verify instead of building your own OTP system saves significant development time and avoids security mistakes. The flow has two API calls: first, send a verification code to the user's phone number; second, check the code the user entered. Twilio handles everything in between. Verify is separate from basic SMS — it uses a Verify Service (identified by a Service SID starting with 'VA') and has its own pricing ($0.05 per verification, separate from message costs).

```
// app/api/twilio/verify/send/route.ts
import twilio from 'twilio';
import { NextResponse } from 'next/server';

const client = twilio(
  process.env.TWILIO_ACCOUNT_SID,
  process.env.TWILIO_AUTH_TOKEN
);

export async function POST(request: Request) {
  try {
    const { phoneNumber } = await request.json();

    const verification = await client.verify.v2
      .services(process.env.TWILIO_VERIFY_SERVICE_SID!)
      .verifications.create({ to: phoneNumber, channel: 'sms' });

    return NextResponse.json({ status: verification.status });
  } catch (error: unknown) {
    const e = error as { message: string };
    return NextResponse.json({ error: e.message }, { status: 500 });
  }
}

// app/api/twilio/verify/check/route.ts
export async function POST(request: Request) {
  try {
    const { phoneNumber, code } = await request.json();

    const check = await client.verify.v2
      .services(process.env.TWILIO_VERIFY_SERVICE_SID!)
      .verificationChecks.create({ to: phoneNumber, code });

    if (check.status === 'approved') {
      return NextResponse.json({ verified: true });
    }
    return NextResponse.json(
      { verified: false, error: 'Invalid or expired code' },
      { status: 400 }
    );
  } catch (error: unknown) {
    const e = error as { message: string };
    return NextResponse.json({ error: e.message }, { status: 500 });
  }
}
```

**Expected result:** POST to /api/twilio/verify/send with a valid phone number sends a 6-digit code via SMS. POST to /api/twilio/verify/check with the phone number and received code returns {verified: true}. The OTP flow works in the Bolt preview.

### 5. Deploy and Configure Incoming Message Webhooks

Outbound SMS, WhatsApp, and Twilio Verify all work in the Bolt preview. However, receiving incoming SMS messages (when someone texts your Twilio number) and receiving voice call webhooks requires Twilio to call an HTTP endpoint on your server. Bolt's WebContainer has no public URL — it runs inside a browser tab that Twilio cannot reach. Deploy to Netlify or Bolt Cloud first. After deployment, go to the Twilio Console → Phone Numbers → Manage → Active Numbers → click your number. In the Messaging Configuration section, set the 'A message comes in' webhook URL to your deployed API endpoint (e.g., https://your-app.netlify.app/api/twilio/incoming-sms). Twilio supports HTTP or HTTPS. Always use HTTPS in production. Create the incoming webhook handler route that parses Twilio's webhook body, extracts the sender number and message, and responds with TwiML (Twilio Markup Language) to control the response.

```
import { NextResponse } from 'next/server';
import twilio from 'twilio';

export async function POST(request: Request) {
  const formData = await request.formData();
  const from = formData.get('From') as string;
  const body = formData.get('Body') as string;
  const messageSid = formData.get('MessageSid') as string;

  console.log(`Incoming SMS from ${from}: ${body}`);
  // Save to database here...

  // Respond with TwiML
  const twiml = new twilio.twiml.MessagingResponse();
  twiml.message('Thanks for your message! We will get back to you soon.');

  return new Response(twiml.toString(), {
    headers: { 'Content-Type': 'text/xml' },
  });
}
```

**Expected result:** After deployment and webhook configuration, text messages sent to your Twilio number arrive at your webhook handler. Senders receive an automatic reply. Incoming messages are saved to your database.

## Best practices

- Store TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN only as server-side environment variables (no NEXT_PUBLIC_ prefix) — these credentials control your entire Twilio account
- Validate phone number format (E.164: +[country code][number]) before sending to Twilio — invalid formats cause cryptic errors and wasted API calls
- Always respond quickly to incoming webhooks (within 15 seconds) with a 200 status — do heavy processing asynchronously after responding to prevent Twilio retry storms
- Use Twilio Verify for OTP instead of building your own code generation — it handles rate limiting, expiry, fraud prevention, and multi-channel delivery out of the box
- Keep SMS messages under 160 characters to send as a single segment and minimize costs — Twilio charges per segment, not per message
- Test outbound SMS thoroughly in the Bolt preview before deploying, but plan from the start to deploy early for testing incoming message flows
- Use Twilio's messaging webhooks to track delivery status (delivered, failed, undelivered) and surface delivery failures to your users rather than showing false success

## Use cases

### Order Confirmation SMS Notifications

Send automated SMS confirmations when users complete purchases, bookings, or form submissions. The SMS contains order details, tracking links, or confirmation numbers. Sending is outbound-only, so it works perfectly in Bolt's preview environment during development.

Prompt example:

```
When a user completes a purchase, send them an SMS confirmation. Create an API route at /api/send-sms that accepts a to phone number (E.164 format) and a message string, then sends an SMS using the Twilio SDK with TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, and TWILIO_PHONE_NUMBER from environment variables. Call this route from the checkout success handler with the message 'Your order #[orderId] is confirmed! Estimated delivery: [date]. Track at: [link]'.
```

### Phone Number OTP Verification

Add phone number verification to your signup flow using Twilio Verify. Users enter their phone number, receive a 6-digit SMS code, and enter it to verify ownership. Twilio handles code generation, expiry (10 minutes), and rate limiting to prevent abuse.

Prompt example:

```
Add phone number verification to my signup form using Twilio Verify. Create two API routes: /api/verify/send (sends a verification code to the phone number using Twilio Verify service SID from TWILIO_VERIFY_SERVICE_SID) and /api/verify/check (verifies the code the user entered). Add a two-step UI: first step shows phone number input with 'Send Code' button, second step shows a 6-digit code input with 'Verify' button. Show countdown timer (10 minutes) and 'Resend Code' option.
```

### WhatsApp Customer Notifications

Send WhatsApp messages to customers who prefer WhatsApp over SMS. Twilio's WhatsApp Business API uses the same SDK as SMS but with a 'whatsapp:' prefix on phone numbers. During development, use Twilio's WhatsApp Sandbox for testing without business approval.

Prompt example:

```
Add WhatsApp messaging to my notification system. Create an API route at /api/send-whatsapp that accepts a to phone number and message, then sends a WhatsApp message using the Twilio SDK with 'whatsapp:' prefix on both the to and from numbers. Use TWILIO_WHATSAPP_NUMBER for the sandbox number. Add a toggle in the notification settings for users to choose SMS or WhatsApp delivery preference.
```

## Troubleshooting

### SMS not received — Twilio returns success but message never arrives

Cause: On Twilio trial accounts, you can only send to verified phone numbers. Unverified numbers silently succeed on the API but the message is not delivered.

Solution: Go to Twilio Console → Phone Numbers → Verified Caller IDs. Add and verify your test phone numbers. Once verified, messages to those numbers will deliver. This restriction is removed when you upgrade from a trial account.

### API route throws 'Authentication Error - No credentials provided' or 401

Cause: TWILIO_ACCOUNT_SID or TWILIO_AUTH_TOKEN environment variables are missing, misspelled, or the .env file hasn't been reloaded.

Solution: Verify both variables are in your .env file without quotes around the values. Account SID starts with 'AC'. The Auth Token is 32 characters of alphanumeric. Restart the Bolt dev server after editing .env since Next.js caches env vars at startup.

```
// In lib/twilio.ts — add validation:
if (!process.env.TWILIO_ACCOUNT_SID || !process.env.TWILIO_AUTH_TOKEN) {
  throw new Error('Missing TWILIO_ACCOUNT_SID or TWILIO_AUTH_TOKEN in environment');
}
```

### Incoming webhook returns 403 or Twilio keeps retrying the webhook

Cause: Twilio expects a 200 status response from webhook handlers within 15 seconds. If your handler throws an error or takes too long, Twilio retries the webhook up to 3 times.

Solution: Ensure your webhook handler always returns a 200 response, even if processing fails. Respond immediately with the TwiML response, then handle business logic (database writes) asynchronously. If signature validation is enabled, verify the X-Twilio-Signature header is checked correctly.

### Incoming webhooks never arrive during development in Bolt preview

Cause: This is a fundamental WebContainer limitation. Bolt's runtime runs inside a browser tab with no publicly accessible URL. Twilio cannot make outbound HTTP calls to your WebContainer.

Solution: Deploy to Netlify or Bolt Cloud first, then configure your Twilio phone number's webhook URL to point to your deployed endpoint. For local development outside Bolt (in VS Code), you could use ngrok to create a temporary public tunnel, but this isn't available within Bolt's WebContainer environment.

## Frequently asked questions

### Does the Twilio SDK work in Bolt's WebContainer?

Yes. The Twilio Node.js SDK is pure JavaScript and communicates with Twilio's REST API over HTTPS. It installs and runs in Bolt's WebContainer without issues. Outbound operations (sending SMS, WhatsApp, initiating calls) work fully in the Bolt preview. The limitation is incoming operations — receiving SMS, voice calls, and webhooks require a publicly accessible URL that the WebContainer cannot provide.

### Can I test SMS sending without a real phone number?

Twilio provides test credentials (separate from your real Account SID/Auth Token, found under Account → API keys & tokens → Test credentials) that simulate API calls without sending real messages or charging your account. Use test phone numbers like +15005550006 (valid number) for simulated success. Switch to real credentials when you're ready to send actual messages to your verified phone number.

### How much does Twilio cost for SMS?

SMS pricing varies by country. In the US, sending costs $0.0079 per message and receiving is $0.0075 per message. Phone numbers cost $1/month each. Twilio's trial account includes $15.50 in credit — enough for nearly 2,000 US messages. Twilio Verify costs $0.05 per verification check (not per code send, but per verification attempt).

### Why can't I receive SMS in the Bolt.new preview?

Receiving SMS requires Twilio to call a webhook URL on your server when a message arrives. Bolt's WebContainer runs inside a browser tab and has no publicly accessible IP address or URL that Twilio can reach. This is a fundamental limitation of the browser-based runtime. To receive SMS, deploy your app to Netlify or Bolt Cloud, then configure your Twilio phone number's webhook URL to point to your deployed API endpoint.

### How do I use WhatsApp with Twilio in Bolt.new?

For WhatsApp, use Twilio's WhatsApp Sandbox during development (go to Messaging → Try it Out → Send a WhatsApp Message in the Twilio Console). The sandbox lets you test without business approval. In your API route, add 'whatsapp:' prefix to both the from and to numbers: from: 'whatsapp:+14155238886' (sandbox number) and to: 'whatsapp:+[user's number]'. Production WhatsApp requires approval from Twilio and Meta, which takes 1-3 business days.

---

Source: https://www.rapidevelopers.com/bolt-ai-integrations/twilio
© RapidDev — https://www.rapidevelopers.com/bolt-ai-integrations/twilio
