Contacto / comentarios: ejemplo con Next.js

Última actualización: Aug 31, 2026Sección: Integraciones

Esta página muestra cómo integrar un webhook de Formulario de contacto / comentarios en una aplicación Next.js usando una ruta BFF: el navegador envía a tu aplicación, que llama a Mailoo con credenciales del servidor. Sin clave API en el cliente.

Esto no es lo mismo que una integración de Form (boletín): los comentarios usan POST /api/v1/webhooks/feedback/... y una integración CONTACT_FORM. Para formularios de suscripción, consulta website-forms{.interpreted-text role="doc"} y website-forms-nextjs-example{.interpreted-text role="doc"}. Para la API cruda (cabeceras, cuerpo, CORS), consulta contact-feedback-form{.interpreted-text role="doc"}.

Requisitos previos

  • Un proyecto de Mailoo con una integración de Formulario de contacto / comentarios
  • Orígenes permitidos (opcional) en la integración --- cuando están configurados y CORS se aplica para solicitudes que envían Origin
  • Una clave API con Envíos de formulario de comentarios (webhook.feedback-submission) si es RESTRICTED, o Acceso completo

Entorno (solo servidor)

Añade a .env.local (o tu entorno de despliegue). Las cuatro variables principales son obligatorias para que el BFF acepte solicitudes.

MAILOO_FEEDBACK_INTEGRATION_API=https://api.mailoo.app
MAILOO_FEEDBACK_INTEGRATION_API_KEY=your-api-key-here
MAILOO_FEEDBACK_INTEGRATION_PROJECT_UID=your-project-uid-here
MAILOO_FEEDBACK_INTEGRATION_ID=your-contact-form-integration-id-here

Opcionales (se fusionan en el metadata de cada envío en el servidor):


# MAILOO_FEEDBACK_INTEGRATION_FORM_NAMESPACE=production-site


# MAILOO_FEEDBACK_INTEGRATION_SITE_ID=my-brand

Lista de permitidos opcional: si se establece, el BFF rechaza envíos cuyo metadata.formKey (o formKey de nivel superior) no esté en la lista (separada por comas). Incluye cada formKey que envían tus UIs (por ejemplo web-contact-page).


# MAILOO_FEEDBACK_INTEGRATION_ALLOWED_FORM_KEYS=web-contact-page,support-widget

Usa solo en el servidor; no uses NEXT_PUBLIC_* para la URL de la API ni la clave.

Múltiples formularios, una integración

Normalmente configuras una integración de comentarios en el entorno pero puedes tener varias UIs (página de contacto, widget de soporte, etc.). Distingue en el cuerpo JSON usando metadata --- por ejemplo formKey (cadena estable por formulario) y entryPoint (p. ej. contact_page, support_widget). La API de Mailoo almacena este objeto en el mensaje y registro de comentario; consulta contact-feedback-form{.interpreted-text role="doc"}.

Múltiples integraciones, múltiples rutas BFF

Cuando necesitas integraciones CONTACT_FORM separadas (diferentes claves API, bandejas de entrada o listas de permitidos), crea una ruta BFF por integración y pasa un prefix de entorno personalizado (o getConfig). No remapees varias integraciones sobre MAILOO_FEEDBACK_INTEGRATION_*.

// app/api/v1/webhooks/team-subscription/submit/route.ts
import { createFeedbackSubmitHandler } from '@mailoo/forms/routes'

export const POST = createFeedbackSubmitHandler({
  prefix: 'MAILOO_TEAM_SUBSCRIPTION_FORM',
})

Entorno para esa ruta (mismo patrón de sufijos que el prefijo de comentarios por defecto):

MAILOO_TEAM_SUBSCRIPTION_FORM_API=https://api.mailoo.app
MAILOO_TEAM_SUBSCRIPTION_FORM_API_KEY=...
MAILOO_TEAM_SUBSCRIPTION_FORM_PROJECT_UID=...
MAILOO_TEAM_SUBSCRIPTION_FORM_INTEGRATION_ID=...

# Opcional:


# MAILOO_TEAM_SUBSCRIPTION_FORM_ALLOWED_FORM_KEYS=pricing-team-request

Los hooks del cliente toman un endpoint apuntando a esa ruta BFF.

Controlador de ruta BFF

Prefiere @mailoo/forms/routes --- no reimplementes la validación ni el proxy del webhook.

Crea app/api/v1/webhooks/feedback/submit/route.ts:

import { createFeedbackSubmitHandler } from '@mailoo/forms/routes'

export const POST = createFeedbackSubmitHandler()
// Opcional: { prefix, getConfig, logger }
// Prefijo por defecto: MAILOO_FEEDBACK_INTEGRATION

La fábrica:

  1. Devuelve 503 si faltan credenciales para el prefijo vinculado (o getConfig).
  2. Valida email / message, fusiona formKey en metadata, aplica ${prefix}_FORM_NAMESPACE, ${prefix}_SITE_ID y ${prefix}_ALLOWED_FORM_KEYS.
  3. Reenvía a ${api}/api/v1/webhooks/feedback/${projectUid}/${integrationId} con X-API-Key y Origin / Referer mediante @mailoo/next-core.

Helper de configuración preferido para validación en layout:

import {
  getMailooFormsIntegrationConfig,
  MAILOO_FEEDBACK_INTEGRATION_PREFIX,
} from '@mailoo/forms'

const config = getMailooFormsIntegrationConfig({
  prefix: MAILOO_FEEDBACK_INTEGRATION_PREFIX,
})

Obsoletos (siguen exportados; no extender): getMailooFeedbackIntegrationConfig, getMailooFormIntegrationConfig, isMailooFeedbackIntegrationConfigured.

Cliente: POST al BFF

Desde un componente cliente, haz POST de JSON a /api/v1/webhooks/feedback/submit con al menos email y message. Incluye metadata.formKey (y cualquier otro contexto) para poder saber qué formulario se usó en el panel de control. O usa useMailooFeedbackSubmit de @mailoo/forms/hooks.

'use client'

async function submitFeedback() {
  const res = await fetch('/api/v1/webhooks/feedback/submit', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      email: 'user@example.com',
      message: 'The checkout button does nothing on mobile.',
      subject: 'Bug report',
      name: 'Jane',
      metadata: {
        formKey: 'web-contact-page',
        pageUrl: typeof window !== 'undefined' ? window.location.href : '',
      },
    }),
  })
  const data = await res.json()
  if (!res.ok) throw new Error(data.message || 'Submit failed')
  return data
}

Maneja 503 (integración no configurada) y 400 (validación o formKey no permitido) en tu UI.

Referencia de paquete

  • Paquete: @mailoo/forms (createFeedbackSubmitHandler de @mailoo/forms/routes, useMailooFeedbackSubmit de @mailoo/forms/hooks) --- consulta nextjs-packages{.interpreted-text role="doc"}

Consulta también

  • contact-feedback-form{.interpreted-text role="doc"} --- endpoint y campos JSON
  • website-forms-nextjs-example{.interpreted-text role="doc"} --- patrón BFF de Form (boletín)
  • nextjs-packages{.interpreted-text role="doc"} --- resumen de @mailoo/forms
  • OpenAPI: https://api.mailoo.app/docs/v1