Saltar al contenido principal

Guía Supabase

Una fila nueva en Supabase,
sale un email y un WhatsApp.

Un database webhook llama a una Edge Function en cada insert, la función hace una llamada API y el mensaje de bienvenida o de pedido sale de tu buzón, de tu número de WhatsApp o de tu móvil Android. Gratis, con el código y un prompt para tu editor de IA.

¿Con prisa? Resume este artículo con una IA

La respuesta corta

¿Cómo enviar email, SMS y WhatsApp desde Supabase?

Crea un database webhook en tu tabla (profiles, orders) que llame a una Edge Function de Supabase en cada INSERT. La función lee la fila nueva y hace una petición POST /message a Unlimited Messaging, que envía el email desde tu buzón, el WhatsApp desde tu número y el SMS desde tu móvil Android. Los database webhooks usan pg_net, así que el insert nunca espera al mensaje.

Supabase no tiene una API para los mensajes que envía tu aplicación. Su servicio de email integrado sirve para los emails de Auth: envía 2 mensajes por hora, solo a direcciones del equipo del proyecto, y Supabase indica que no está pensado para producción. Un email de bienvenida, una confirmación de pedido o un WhatsApp al cliente te toca enviarlos a ti.

Una Edge Function es el lugar adecuado: se ejecuta en el servidor, lee los secretos con Deno.env.get y el plan Free de Supabase incluye 500.000 invocaciones. Lo habitual es un proveedor por canal, una API de email, Twilio para SMS, la Cloud API de Meta para WhatsApp: tres claves, tres facturas. Aquí una sola petición cubre los tres canales, y el plan Free de Unlimited Messaging no cobra por mensaje.

Esta guía cubre los mensajes que envía tu aplicación. Los emails de Auth (confirmación de registro, magic link, restablecer contraseña) y el OTP por teléfono siguen en los ajustes de Supabase Auth, donde conectas un servidor SMTP o un proveedor de SMS.

Lee también: email y WhatsApp en una sola petición API, y la API de SMS gratis que envía desde tu propio móvil.

Ilustración: nodos de automatización que unen un disparador con un mensaje y un correo, con el titular «Una fila en Supabase, un mensaje enviado».

Paso a paso

¿Cómo se monta, paso a paso?

Cinco pasos, unos 15 minutos. Necesitas un proyecto de Supabase, la CLI de Supabase y una cuenta gratis de Unlimited Messaging.

  1. Conecta tus canales y crea una clave API

    En la app de Unlimited Messaging, vincula tu número de WhatsApp con un código QR, conecta tu buzón por IMAP/SMTP (sirve una contraseña de aplicación de Gmail) y, para SMS, inicia sesión en la app Android gratuita en un móvil con SIM. Conecta solo los canales que uses y crea una clave API.

    supabase/functions/.env.env
    # supabase/functions/.env (gitignored, local only)
    # Created at app.unlimitedmessaging.app > API keys
    UM_API_KEY=um_live_xxxx
    # Any long random string, shared with the database webhook
    WEBHOOK_SECRET=change-me-to-a-long-random-string
  2. Crea la función y guarda los secretos

    Crea la función con la CLI y sube los dos secretos a tu proyecto. Solo viven en el entorno de la función: nunca pongas la clave API en una variable VITE_ o NEXT_PUBLIC_, ni en ningún código del frontend.

    TerminalSupabase CLI
    supabase functions new notify-signup
    
    # Push the secrets to your project (never to the frontend)
    supabase secrets set --env-file supabase/functions/.env
    supabase secrets list
  3. Escribe la función

    La función comprueba el secreto compartido, lee la fila insertada, envía el email siempre y el WhatsApp solo si la fila tiene número. priority: transactional pone el mensaje por delante de cualquier envío masivo que espere en tu cola.

    notify-signup/index.tsDeno / TypeScript
    // supabase/functions/notify-signup/index.ts
    type Profile = { id: string; email: string; phone: string | null; full_name: string | null };
    type WebhookPayload = {
      type: 'INSERT' | 'UPDATE' | 'DELETE';
      table: string;
      schema: string;
      record: Profile;
      old_record: Profile | null;
    };
    
    Deno.serve(async (req) => {
      // The database webhook sends this header; nobody else knows it
      if (req.headers.get('x-webhook-secret') !== Deno.env.get('WEBHOOK_SECRET')) {
        return new Response('Unauthorized', { status: 401 });
      }
    
      const { record } = (await req.json()) as WebhookPayload;
      const name = record.full_name ?? 'there';
    
      // Email always, WhatsApp when the row has a phone (E.164: +33612345678).
      // Use { channel: 'SMS' } instead for people who are not on WhatsApp.
      const channels: Array<{ channel: 'EMAIL' | 'WHATSAPP' | 'SMS' }> = [{ channel: 'EMAIL' }];
      if (record.phone) channels.push({ channel: 'WHATSAPP' });
    
      const res = await fetch('https://api.unlimitedmessaging.app/message', {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${Deno.env.get('UM_API_KEY')}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          to: { email: record.email, phone: record.phone ?? undefined },
          channels,
          subject: 'Welcome aboard',
          text: `Hi ${name}, your account is ready. Reply to this message if you need anything.`,
          priority: 'transactional',
        }),
      });
    
      if (!res.ok) console.error('Unlimited Messaging', res.status, await res.text());
      return new Response(null, { status: res.ok ? 200 : 502 });
    });
  4. Despliégala, protegida por tu propio secreto

    Un database webhook no envía un JWT de usuario: desactiva la verificación de la plataforma solo para esta función (--no-verify-jwt, o verify_jwt = false en config.toml). La cabecera x-webhook-secret que comprueba la función deja fuera a los desconocidos.

    TerminalSupabase CLI
    # A database webhook sends no user JWT: turn the platform check off
    # for this function only, the x-webhook-secret header protects it
    supabase functions deploy notify-signup --no-verify-jwt
    
    # Or keep it in supabase/config.toml:
    # [functions.notify-signup]
    # verify_jwt = false
  5. Crea el database webhook

    En el dashboard, Database > Webhooks: elige la tabla (aquí profiles), el evento Insert, el tipo Supabase Edge Functions y la función notify-signup, y añade una cabecera x-webhook-secret con el mismo valor. Inserta una fila de prueba: este es el cuerpo que recibe la función.

    Cuerpo del POSTWebhook payload
    {
      "type": "INSERT",
      "table": "profiles",
      "schema": "public",
      "record": {
        "id": "8f1c2d3e-0000-4000-8000-000000000000",
        "email": "[email protected]",
        "phone": "+33612345678",
        "full_name": "Lea"
      },
      "old_record": null
    }

Vibe coding

¿Programas con Lovable, Cursor o Claude Code? Pega este prompt

El prompt le da a tu editor de IA el patrón exacto: una Edge Function, los secretos en Supabase, una llamada REST. Te pregunta antes de enviar nada de verdad.

Prompt para copiar
Añade notificaciones transaccionales a este proyecto de Supabase con Unlimited Messaging (email, WhatsApp y SMS enviados desde mis propias cuentas).

1. Crea una Edge Function de Supabase llamada notify-signup. Lee UM_API_KEY y WEBHOOK_SECRET con Deno.env.get. Nunca pongas la clave en el código del frontend ni en una variable VITE_ / NEXT_PUBLIC_.
2. La función recibe el payload de un database webhook de Supabase { type, table, schema, record, old_record }. Devuelve 401 si la cabecera x-webhook-secret no es igual a WEBHOOK_SECRET.
3. Envía un POST https://api.unlimitedmessaging.app/message con la cabecera Authorization: Bearer UM_API_KEY y el JSON { to: { email, phone }, channels: [{ channel: 'EMAIL' }, { channel: 'WHATSAPP' }], subject, text, priority: 'transactional' }. Añade WHATSAPP (o SMS) solo si la fila tiene un número en formato E.164.
4. Dame los comandos: supabase secrets set, supabase functions deploy notify-signup --no-verify-jwt, y cómo crear el database webhook en el INSERT de mi tabla con la cabecera x-webhook-secret.
5. Referencia de la API: https://docs.unlimitedmessaging.app. Creo la clave API en https://app.unlimitedmessaging.app.

Pregúntame qué tabla y qué texto de mensaje usar antes de escribir el código.

Las opciones

¿Qué opción para enviar mensajes desde Supabase?

Cuatro formas de enviar una notificación cuando llega una fila a tu base de datos, del servicio integrado a una sola API para todos los canales.

¿Qué opción para enviar mensajes desde Supabase?
Email integrado de SupabaseSolo emails de AuthResend desde una funciónAPI de emailTwilio desde una funciónAPI de SMS y WhatsAppUnlimited MessagingEmail, WhatsApp y SMS
CanalesSolo emails de AuthEmailSMS y WhatsApp, cobrados por mensajeEmail, WhatsApp y SMS en una petición
Gratis2 emails por hora, solo direcciones del equipo3.000 emails al mes, 100 al díaPrueba: hasta 5 números verificadosPlan Free sin coste por mensaje
RemitenteLa dirección de SupabaseTu dominio verificadoUn número de Twilio o un remitente de WhatsApp registradoTu propio buzón, tu número de WhatsApp y tu móvil
Mensajes de WhatsAppNoNoPlantillas aprobadas por Meta para iniciar una conversaciónTexto libre desde tu número vinculado
ConfiguraciónNingunaRegistros DNS de tu dominioCuenta, número, registro del remitente de WhatsAppCódigo QR, acceso IMAP/SMTP, app Android
Ideal paraProbar los flujos de AuthEmail en gran volumenSMS en volumen, WhatsApp oficialMensajes de una app uno a uno, gratis mientras creces

Comprobado el 9 de noviembre de 2026 en supabase.com, resend.com/pricing y la documentación de prueba de Twilio (enlaces en las fuentes). Los planes gratis cambian: sigue los enlaces antes de construir sobre uno.

La letra pequeña

¿Cuáles son los límites?

Gratis quita la factura por mensaje. No quita las reglas de WhatsApp, de tu móvil ni de tu buzón.

  1. WhatsApp es no oficial, y el spam hace que bloqueen números

    Tu número se vincula como un dispositivo, fuera de la plataforma Business de Meta. Escribir a clientes registrados que esperan el mensaje es de bajo riesgo; los envíos masivos a desconocidos pueden hacer que bloqueen el número. Usa WhatsApp para mensajes transaccionales.

  2. El SMS necesita un móvil Android encendido

    Los SMS salen de la SIM del móvil, con tu tarifa. Android pide confirmación a partir de 30 SMS en 30 minutos, así que la app espacia los envíos a unos 30 cada 30 minutos: bien para registros y pedidos, no para un envío masivo el día del lanzamiento.

  3. El email sigue los límites de tu buzón

    Los emails salen de tu buzón por SMTP, así que se aplica su tope diario: 500 al día en una cuenta de Gmail. Para newsletters a miles de personas, usa un servicio de email masivo.

  4. Los mensajes del plan Free llevan una firma

    En el plan Free, los mensajes terminan con una línea corta "Sent with UnlimitedMessaging.app", y los archivos multimedia y los webhooks son de pago. Medium y Max quitan la línea.

  5. El insert no espera al mensaje

    pg_net envía la petición de forma asíncrona: una función que falla nunca deshace el insert. Registra la respuesta de la API en la función y vigila sus logs.

  6. La clave se queda en el servidor

    Cualquiera que abra tu bundle del frontend puede reutilizar una clave que esté ahí. La clave va en los secretos de la Edge Function, y el secreto del webhook impide que desconocidos llamen a tu función.

FAQ

Preguntas sobre enviar mensajes desde Supabase

Ilian, ingeniero de software senior

Escrito por

· Ingeniero de software senior

Ingeniero de software senior, funda y dirige varias empresas tecnológicas. Diseña productos en torno a las API de mensajería, la automatización y la integración de la IA, y comparte aquí lo que aprende construyendo.

Ver el perfil de LinkedInActualizado el

Envía hoy tu primera notificación desde Supabase.

Crea una cuenta gratis, conecta un buzón o un número de WhatsApp y pega la función. Sin tarjeta, sin coste por mensaje.