Sync unsubscribes to your database
Push every subscription change out of Bitelio and into your own user table with a workflow's webhook step
Whenever a contact's subscribed flag turns off — whether from a manual edit, the hosted unsubscribe page, a bounce, or a spam complaint — Bitelio emits contact.unsubscribed. A workflow listening for that event can relay it straight to your backend through a WEBHOOK step.
Setup
Build the receiving endpoint
Expose a public HTTPS route that checks a shared secret before touching the user record. Keep the handler fast — webhook deliveries are cut off after 10 seconds, so push anything slow onto a queue.
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();
});When the unsubscribe was automatic, event.reason carries "bounce" or "complaint"; for manual or self-service opt-outs the field simply isn't there.
Create the workflow
Under Workflows → New workflow:
- Trigger:
EVENToncontact.unsubscribed - Add a
WEBHOOKstep:- URL:
https://api.example.com/bitelio/unsubscribes - Headers:
{ "Authorization": "Bearer your-shared-secret" } - Leave the body empty so Bitelio sends the default payload.
- URL:
Turn the workflow on.
Mirroring resubscribes
For the opposite direction of the flag, clone the same structure into a second workflow triggered on contact.subscribed. Don't merge the two into one branched flow — a pair of small, single-purpose workflows is much simpler to keep an eye on.
The reverse direction
When the authoritative copy lives on your side — say a user flips their email preference inside your own settings page — push the change to Bitelio with PATCH /contacts/:id from your backend:
curl -X PATCH https://api.bitelio.com/contacts/cnt_abc \
-H "Authorization: Bearer sk_your_secret_key" \
-d '{"subscribed": false}'Be aware this update emits contact.unsubscribed too, so the webhook you built above will echo the change right back to your handler. Since the write is idempotent the loop is normally harmless — just don't be surprised by it.