v19.0

Notifuse/notifusev19.0Dec 1, 2025by pierre-b

AI Summary

Release v19.0 introduces Outgoing Webhooks - a major new feature enabling real-time HTTP notifications when workspace events occur. This release also adds native support for the `full_name` contact field, includes important bug fixes for timeline timestamps and JSON filters, and requires a database migration that renames the `webhook_events` table to `inbound_webhook_events`.

Key Highlights

  • Outgoing Webhooks - Subscribe to workspace events and receive HTTP notifications with HMAC-SHA256 signature verification
  • Contact `full_name` field - New native field available in Liquid templates and webhook payloads
  • Bug fix: Timeline timestamps now use database `CURRENT_TIMESTAMP` instead of application time
  • Bug fix: JSON filters now accept number and time values without validation failures
  • Database migration required: `webhook_events` table renamed to `inbound_webhook_events`

Breaking Changes

  • Table `webhook_events` renamed to `inbound_webhook_events` - custom queries and reports need to be updated

New Features

  • Outgoing Webhooks with full CRUD API (`/api/webhookSubscriptions.*`)
  • Support for 20+ event types including contact.created, email.sent, list.subscribed, segment.joined, custom_event.created
  • Automatic retries with exponential backoff (up to 10 attempts over 24h)
  • Custom event filters for fine-grained subscription control
  • Test webhook endpoint for integration debugging
  • Delivery logs with 7-day automatic cleanup
  • Contact `full_name` field available in templates via `{{ contact.full_name }}` and tracked in contact timeline
  • Segment filters using `entity_type: "webhook_event"` automatically migrated to `"inbound_webhook_event"`

Full Release Notes

# Release v19.0

**Release Date:** December 1, 2025

---

## Highlights

This release introduces **Outgoing Webhooks** - a powerful new feature that allows you to subscribe to workspace events and receive HTTP notifications in real-time. It also adds native support for the `full_name` contact field and includes bug fixes.

---

## New Features

### Outgoing Webhooks

Subscribe to workspace events and receive HTTP notifications to integrate Notifuse with your external systems.

<img width="1327" height="869" alt="webhook_settings" src="https://github.com/user-attachments/assets/3642553e-fafe-4bbb-aa98-f93a216fbacb" />

- **CRUD API** for webhook subscriptions (`/api/webhookSubscriptions.*`)
- **Event types supported:**
  - `contact.created`, `contact.updated`, `contact.deleted`
  - `email.sent`, `email.delivered`, `email.opened`, `email.clicked`, `email.bounced`, `email.complained`, `email.unsubscribed`
  - `list.subscribed`, `list.unsubscribed`, `list.confirmed`, `list.pending`
  - `segment.joined`, `segment.left`
  - `custom_event.created`, `custom_event.updated`, `custom_event.deleted`
- **Security:** HMAC-SHA256 signature verification (Standard Webhooks spec)
- **Reliability:** Automatic retries with exponential backoff (up to 10 attempts over 24h)
- **Flexibility:** Custom event filters for fine-grained subscription control
- **Debugging:** Test webhook endpoint for integration debugging
- **Retention:** Delivery logs with 7-day automatic cleanup

### Contact `full_name` Field

New native field for systems that don't separate first and last names. The `full_name` field:

- Can be set independently of `first_name`/`last_name`
- Is available in Liquid templates via `{{ contact.full_name }}`
- Is included in webhook payloads
- Is tracked in contact timeline

---

## Bug Fixes

- **Timeline timestamps:** Fixed incorrect times in contact timeline (now uses `CURRENT_TIMESTAMP` in database triggers instead of application time)
- **JSON filters:** Fixed validation failures when using number or time values in JSON field segment filters (#140)

---

## Breaking Changes

### Table Rename: `webhook_events` → `inbound_webhook_events`

To distinguish between incoming webhook events (from ESPs) and outgoing webhooks (to your systems), the `webhook_events` table has been renamed to `inbound_webhook_events`.

**Impact:**

- If you have custom queries or reports using `webhook_events`, update them to use `inbound_webhook_events`
- Segment filters using `entity_type: "webhook_event"` are automatically migrated to `"inbound_webhook_event"`
- Contact timeline entries are automatically updated

---

## Database Migration

Migration v19.0 performs the following changes:

1. Expands `contact_timeline.entity_type` column from VARCHAR(20) to VARCHAR(50)
2. Renames `webhook_events` table to `inbound_webhook_events` (with all indexes)
3. Creates `webhook_subscriptions` table for outgoing webhook configuration
4. Creates `webhook_deliveries` table for delivery tracking and retry queue
5. Adds `full_name` column to `contacts` table
6. Updates `track_contact_changes()` trigger to include `full_name` in timeline
7. Creates database triggers for webhook event generation on all relevant tables

---

## API Reference

### New Endpoints

| Endpoint                                  | Method | Description                       |
| ----------------------------------------- | ------ | --------------------------------- |
| `/api/webhookSubscriptions.create`        | POST   | Create a new webhook subscription |
| `/api/webhookSubscriptions.update`        | POST   | Update an existing subscription   |
| `/api/webhookSubscriptions.delete`        | POST   | Delete a subscription             |
| `/api/webhookSubscriptions.get`           | GET    | Get subscription details          |
| `/api/webhookSubscriptions.list`          | GET    | List all subscriptions            |
| `/api/webhookSubscriptions.test`          | POST   | Send a test webhook               |
| `/api/webhookSubscriptions.getDeliveries` | GET    | Get delivery logs                 |

### Webhook Payload Format

```json
{
  "id": "del_abc123",
  "timestamp": "2025-12-01T10:30:00Z",
  "type": "contact.created",
  "data": {
    "email": "user@example.com",
    "first_name": "John",
    "last_name": "Doe",
    "full_name": "John Doe"
  }
}
```

### Signature Verification

Webhooks are signed using HMAC-SHA256. Verify using the `Webhook-Signature` header:

```
Webhook-Signature: v1,t=1701432600,s=abc123...
```

---

## Upgrade Instructions

1. **Backup your database** before upgrading
2. Update to v19.0
3. The migration runs automatically on startup
4. Verify webhook_events queries are updated to use inbound_webhook_events

---

## Full Changelog

See [CHANGELOG.md](./CHANGELOG.md) for the complete list of changes.