# Sincroniza bajas con tu base de datos (/es/recipes/sync-unsubscribes)

Cada vez que el indicador `subscribed` de un contacto se desactiva — ya sea por una edición manual, la página de baja alojada, un rebote, o una queja de spam — Bitelio emite `contact.unsubscribed`. Un flujo de trabajo que escuche ese evento puede reenviarlo directamente a tu backend mediante un paso `WEBHOOK`.

## Configuración

import {Step, Steps} from 'fumadocs-ui/components/steps';

<Steps>
  <Step>
    ### Construye el endpoint receptor

    Expón una ruta HTTPS pública que verifique un secreto compartido antes de tocar el registro del usuario. Mantén el manejador rápido — las entregas de webhook se cortan a los 10 segundos, así que empuja cualquier cosa lenta a una cola.

    ```ts
    app.post('/bitelio/unsubscribes', async (req, res) => {
      if (req.header('authorization') !== `Bearer ${process.env.BITELIO_WEBHOOK_SECRET}`) {
        return res.status(401).end();
      }

      const { contact, event } = req.body;
      await db.user.update({
        where: { email: contact.email },
        data: {
          emailSubscribed: false,
          emailUnsubscribedReason: event.reason ?? 'user_action',
        },
      });

      res.status(204).end();
    });
    ```

    Cuando la baja fue automática, `event.reason` lleva `"bounce"` o `"complaint"`; para las bajas manuales o por autoservicio el campo simplemente no está presente.
  </Step>

  <Step>
    ### Crea el flujo de trabajo

    En **Flujos de trabajo → Nuevo flujo de trabajo**:

    * **Disparador**: `EVENT` en `contact.unsubscribed`
    * Añade un paso `WEBHOOK`:
      * **URL**: `https://api.example.com/bitelio/unsubscribes`
      * **Encabezados**: `{ "Authorization": "Bearer your-shared-secret" }`
      * Deja el cuerpo vacío para que Bitelio envíe la [carga útil por defecto](/es/guides/webhooks#webhook-payload).

    Activa el flujo de trabajo.
  </Step>
</Steps>

## Reflejar las resuscripciones

Para la dirección opuesta del indicador, clona la misma estructura en un segundo flujo de trabajo disparado en `contact.subscribed`. No fusiones los dos en un flujo único con ramas — un par de flujos de trabajo pequeños y de propósito único es mucho más fácil de vigilar.

## La dirección inversa

Cuando la copia autoritativa vive de tu lado — digamos que un usuario cambia su preferencia de correo dentro de tu propia página de ajustes — envía el cambio a Bitelio con `PATCH /contacts/:id` desde tu backend:

```bash
curl -X PATCH https://api.bitelio.com/contacts/cnt_abc \
  -H "Authorization: Bearer sk_your_secret_key" \
  -d '{"subscribed": false}'
```

Ten en cuenta que esta actualización también emite `contact.unsubscribed`, así que el webhook que construiste arriba reflejará el cambio de vuelta a tu manejador. Como la escritura es idempotente, el ciclo normalmente es inofensivo — simplemente no te sorprenda.

## Qué sigue

<Cards>
  <Card title="Webhooks" href="/es/guides/webhooks">
    Referencia completa del paso webhook: estructura de la carga útil y notas de seguridad.
  </Card>

  <Card title="Páginas de baja" href="/es/guides/unsubscribe-pages">
    Páginas de preferencias alojadas y las variables de URL disponibles en las plantillas.
  </Card>
</Cards>
