feat(webhooks): enrich event.* payloads with customer contact + share_token (#341)
The event.published webhook reporter wired into n8n to send WhatsApp
gallery links was missing the data needed to actually message the
customer — only event_name + share_url were in the payload, no
customer_name / customer_email / customer_phone, and no bare share
token to construct alternate URLs.
Adds a single canonical event subject helper (webhookService.buildEventSubject)
so every event.* webhook returns the same shape:
{ id, slug, event_name, event_type, event_date,
share_url, share_token,
customer_name, customer_email, customer_phone }
Fields the caller does not have in scope come back as null — keys are
always present so receivers do not have to distinguish "field missing"
from "field null". Pure addition: existing receivers continue to work,
existing templates ${data.event.event_name} keep working, and new
templates can now reference ${data.event.customer_phone} etc.
Wired into all five firing sites:
- routes/events.js — public event create (created + published)
- routes/adminEvents.js — admin create + draft→publish
- routes/v1/events.js — public v1 API (created + published)
- services/expirationChecker.js — event.expired (extra: expires_at)
- services/archiveService.js — event.archived (extra: archive_path)
PII surface area widens (customer email/phone now flow to webhook
receivers), so:
- Settings → Webhooks UI gets an amber Callout above the create form
warning admins to only point webhooks at receivers they trust.
- Docs page updated with the new payload sample, the always-present
null contract, and a Callout warning.
Verified end-to-end against the local dev webhook receiver — delivered
payload contains all 10 fields. webhookDelivery integration suite
remains 8/8 green.
This commit is contained in:
@@ -130,6 +130,20 @@ export const WebhooksTab: React.FC = () => {
|
||||
{t('settings.webhooks.subtitle', 'POST event notifications to your URL the moment something happens — gallery published, photo uploaded, event archived, etc. Signed with HMAC-SHA256 in the X-PicPeak-Signature header.')}
|
||||
</p>
|
||||
|
||||
{/* PII notice (#341). event.* payloads include customer contact
|
||||
fields (name / email / phone) plus the share token. Make sure
|
||||
admins know what flows to a webhook receiver before they wire
|
||||
one up to a third-party automation tool. */}
|
||||
<div className="rounded-lg border border-amber-300 bg-amber-50 dark:border-amber-700/50 dark:bg-amber-900/20 p-3 mb-4 flex items-start gap-2.5">
|
||||
<AlertTriangle className="w-4 h-4 text-amber-600 dark:text-amber-400 flex-shrink-0 mt-0.5" />
|
||||
<p className="text-xs text-amber-900 dark:text-amber-200 leading-relaxed">
|
||||
{t(
|
||||
'settings.webhooks.piiNotice',
|
||||
'event.* payloads include customer contact info (name, email, phone) and the gallery share token if you have stored them. Only point webhooks at receivers you trust — they have everything needed to message the customer or open the gallery.'
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{justCreatedSecret && (
|
||||
<div className="rounded-lg border border-amber-300 bg-amber-50 dark:bg-amber-900/20 p-4 mb-4">
|
||||
<div className="flex items-start gap-3">
|
||||
|
||||
Reference in New Issue
Block a user