Save 44% with yearly billing.View Plans
textbee Logotextbee.dev

AI app builder

Add SMS to a v0 app: Next.js route handlers that text from your own phone

Published and updated

A v0 app is a Next.js app on Vercel, so SMS goes in a route handler. Add TEXTBEE_API_KEY as an environment variable in the project settings, ask v0 for a route that posts to the textbee send endpoint, and call that route from your page. Publish once to get a stable vercel.app URL, then register a second route as the textbee webhook for replies.

Send
HTTP POST
to the textbee send endpoint
Receive
Webhook
MESSAGE_RECEIVED, flat JSON
Pace
10 to 15 / min
per Android phone
textbee code
None
uses what the tool ships today

What you need

  • A v0 project. Environment variables and API routes work on every v0 plan.
  • A textbee account with the Android app installed on the phone that holds the SIM, and an API key from the dashboard.
  • A published deployment for replies: textbee needs a stable public URL.
  • The textbee app on the phone. Download the app, then create an API key in the dashboard.

Send SMS from v0

Only variables that start with NEXT_PUBLIC_ reach the browser in Next.js. TEXTBEE_API_KEY without that prefix stays on the server, which is where the route handler runs.

  1. Add the environment variable

    Open the project menu, Settings, then Environment Variables. Add the key for Development as well as Production: the v0 preview only sees variables available to the Development environment. v0 also prompts for missing keys after it generates code that needs them.

    FieldValue
    KeyTEXTBEE_API_KEY
    EnvironmentsDevelopment, Preview, Production
  2. Prompt for the route handler

    Paste the prompt from this page. v0 writes a route like this one and a form or button that calls it.

    app/api/sms/route.ts
    export async function POST(req: Request) {
      const { to, message } = await req.json()
      const res = await fetch('https://api.textbee.dev/api/v1/gateway/send-sms', {
        method: 'POST',
        headers: {
          'x-api-key': process.env.TEXTBEE_API_KEY ?? '',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ recipients: [to], message }),
      })
      return Response.json(await res.json(), { status: res.status })
    }
  3. Limit who can call it

    Ask v0 to check the session in the route, or to take a record id and build the message on the server. An open route that texts any number with any message is an open relay for your phone.

  4. Test in the preview

    Send to your own number from the preview. The route returns data.success true and an smsBatchId, and the dashboard shows the message as sent, then delivered.

Receive SMS in v0

Replies go to a second route handler. Read the raw body with req.text() before parsing it, because the signature covers the exact bytes textbee sent.

  1. Prompt for the webhook route

    Ask v0 for app/api/textbee/webhook/route.ts that verifies X-Signature with TEXTBEE_WEBHOOK_SECRET and handles MESSAGE_RECEIVED.

    app/api/textbee/webhook/route.ts
    import { createHmac, timingSafeEqual } from 'node:crypto'
    
    export async function POST(req: Request) {
      const raw = await req.text()
      const expected = createHmac('sha256', process.env.TEXTBEE_WEBHOOK_SECRET ?? '').update(raw).digest('hex')
      const given = req.headers.get('x-signature') ?? ''
      if (given.length !== expected.length || !timingSafeEqual(Buffer.from(given), Buffer.from(expected))) {
        return new Response('invalid signature', { status: 401 })
      }
      const event = JSON.parse(raw)
      if (event.webhookEvent === 'MESSAGE_RECEIVED') {
        // store event.sender, event.message, event.receivedAt
      }
      return new Response('ok')
    }
  2. Publish for a stable URL

    Click Publish in the chat header and confirm the vercel.app domain. Later changes go out with Publish Changes and keep the same production URL.

  3. Register the webhook

    Add https://<your-project>.vercel.app/api/textbee/webhook in the textbee dashboard under Webhooks with the MESSAGE_RECEIVED event and the same signing secret.

Paste this prompt into v0

The prompt below carries the endpoints, the payloads, where the key may live and the v0 details from this page. Change the line that starts with What I want, and v0 builds the feature without guessing an endpoint.

Prompt for your AI agent

Paste it into the v0 chat. It carries the textbee API facts and the v0 details the agent needs, so it does not guess.

Add SMS to the app I am building in v0. Use textbee, an SMS gateway that sends and receives SMS through my own Android phone.

Facts about the textbee API. Use only these. Do not invent endpoints or fields.
- Send an SMS: POST https://api.textbee.dev/api/v1/gateway/send-sms with the header x-api-key: <TEXTBEE_API_KEY> and a JSON body like {"recipients": ["+12015550123"], "message": "Hello"}. recipients must be a JSON array of E.164 numbers, even for one number. Optional fields: deviceId, simSubscriptionId, scheduledAt (ISO 8601, in the future). The response is {"data": {"success": true, "smsBatchId": "..."}}.
- Check delivery or read replies: GET https://api.textbee.dev/api/v1/gateway/messages with the same header. Filters: direction=received, smsBatchId=<id from the send>, from and to as ISO timestamps. Each row has a status such as sent, delivered, failed or received.
- Receive an SMS: textbee posts JSON to a webhook URL I register in the dashboard. A MESSAGE_RECEIVED delivery has these top-level fields: smsId, message, deviceId, webhookSubscriptionId, webhookEvent, idempotencyKey, sender, receivedAt. The header X-Signature holds an HMAC-SHA256 hex digest of the raw body, keyed with the signing secret I set on the webhook. Retries reuse the same idempotencyKey.
- Limits: One Android phone sends roughly 10 to 15 messages a minute. Text only, no MMS. Messages over 160 characters are split into segments.

Rules:
- Store the API key as a secret named TEXTBEE_API_KEY. Call textbee only from server-side code, never from code that runs in the browser.
- Do not ask me to paste the real key into this chat. Tell me where to add the secret instead.
- For incoming texts, create a public server endpoint, check the X-Signature header against a secret named TEXTBEE_WEBHOOK_SECRET, and ignore a repeated idempotencyKey.

What I want: Add a contact form that texts me each new message, and show replies from customers on an admin page.

v0 specifics you should know:
- This is a Next.js App Router app on Vercel. Put textbee calls in route handlers under app/api or in server actions.
- Read TEXTBEE_API_KEY and TEXTBEE_WEBHOOK_SECRET from process.env. Never use the NEXT_PUBLIC_ prefix for them.
- Environment variables are added under the project menu, Settings, Environment Variables. The preview only sees Development variables.
- The webhook route must read the raw body with req.text() before JSON.parse, so the signature check works.

Build it, tell me where to add each secret in v0, and add a way to send one test message to my own number.

Features to build

Contact form to text
A server action posts the form to your database and texts you the name and the first line. You answer from your phone, and the reply comes back through the webhook route.
Status page alerts
A Vercel cron job hits a route that checks your service and texts you when a check fails twice in a row.
Appointment confirmations
The booking server action texts a confirmation with a reply prompt. YES or NO arrives at the webhook and updates the booking.
Admin inbox
An admin page lists stored replies and posts answers through the send route, so the whole conversation stays in your app.

Why v0 builders text from their own phone

Works in the preview
There is no trial mode that limits who you can text. The same key texts your own number in the preview and real customers in production.
Nothing to install
No SDK, no marketplace integration, no number to buy. One environment variable and one fetch call in a route handler.
A number people answer
A text from a mobile number gets a reply. The reply reaches your route as JSON, so a contact form becomes a two-way conversation.

A cloud SMS provider in v0 vs textbee in v0

What you care aboutCloud SMS providertextbee
SetupSign up, verify, buy a number, register a sender, add the provider SDK and its keysPair a phone, add one environment variable, paste one prompt
Sender the contact seesA rented virtual number, or an alphanumeric sender where the country allows itYour own mobile number, which your contacts already have saved
Monthly costPer message, plus number rental and carrier surcharges in some countriesA flat plan with messages included: Pro is $14.99 a month for 5,000 messages. No per-message fee, no number rental, no carrier surcharge.
ThroughputSet by the provider tier and by sender registrationOne phone sends roughly 10 to 15 messages a minute. Add phones to scale.
RepliesInbound webhook from the provider, or the provider app in the tooltextbee webhook: flat JSON, signed with HMAC-SHA256
Where the message leaves fromThe provider data centerAn Android phone you own, plugged in, on Wi-Fi or mobile data
v0 costv0 credits for the prompts, plus the provider billv0 credits for the prompts only

Per-message prices by provider and country, with sources and dates, are on the provider comparison pages.

What works and what does not

Works today

  • Sends from route handlers and server actions
  • Replies on a webhook route at your vercel.app or custom domain
  • Scheduled sends from Vercel cron jobs
  • Different keys per environment through Development, Preview and Production variables

Not with this route

  • Calls from client components or NEXT_PUBLIC_ variables
  • Webhooks to a preview URL that changes on every deployment; use the production URL
  • MCP tools inside the generated app: v0 uses MCP servers only while it generates
  • MMS

What v0 charges

v0 Free is $0 with a daily message limit and a $5 one-time credit for new users. Plus is $30 per user a month and Business $100 per user a month. Environment variables and API routes are not gated by plan. v0.app, checked on October 22, 2026. textbee itself charges a flat monthly plan with messages included; see pricing.

Frequently asked questions

Why does my v0 preview say TEXTBEE_API_KEY is undefined?

The preview only reads variables available to the Development environment. Edit the variable under Settings, Environment Variables and tick Development, then reload the preview.

Can I use the textbee MCP server in v0?

For building, yes: open the + menu in the prompt form, choose MCPs, add https://mcp.textbee.dev/mcp and pick Custom Headers with x-textbee-api-key. v0 can then send a test text while it works. The app it generates cannot call MCP tools, so it uses the route handler.

Should I use a server action or a route handler?

A server action fits a form in your own app. A route handler fits anything that calls in from outside, such as the textbee webhook or a cron job. Both run on the server and can read TEXTBEE_API_KEY.

Does the webhook route work on a custom domain?

Yes. Register the route on the domain you serve from. When you add a custom domain later, update the webhook URL in the textbee dashboard or keep the vercel.app URL there, since it keeps working.

Is there a textbee integration in the Vercel Marketplace?

No. This route uses an environment variable and a route handler, which works in any Vercel project without a marketplace install.

Why does the signature check fail on Vercel?

Usually because the code parsed the JSON first and signed the re-serialized string. Sign the exact text from req.text(), compare in constant time, and make sure TEXTBEE_WEBHOOK_SECRET matches the secret on the textbee webhook.

How long does the setup take?

About ten minutes: pair the phone, create an API key, add the environment variable and paste the prompt. Replies need one publish and a webhook in the textbee dashboard.

Can I export the v0 code and keep the SMS feature?

Yes. The route handlers are plain Next.js code. Deploy the project anywhere that runs Next.js, set the two environment variables, and point the textbee webhook at the new domain.

Sources

  1. v0.app, checked on October 22, 2026
  2. v0.app: External APIs and environment variables, checked on October 22, 2026
  3. v0.app: Deployments, checked on October 22, 2026
  4. v0.app: MCP, checked on October 22, 2026

Read next

Your phone is already an SMS gateway. Switch it on.

Set up in minutes and send your first message for free. No credit card, no per-message fees, no carrier contracts.

Free tier forever No credit card required Open source

Need self-hosting help or a custom integration? See services