Skip to content

Webhooks

Overview

NOMA Sync receives webhooks from three platforms. Do not call these endpoints directly — they are configured in each platform’s dashboard. This page summarizes what each webhook sends and how NOMA Sync uses it.

Givebutter

Endpoint: POST /webhooks/givebutter
Auth: Signature verification (if GIVEBUTTER_WEBHOOK_SECRET or equivalent is set).

Events

  • transaction.succeeded – New donation or ticket purchase. Primary event for syncing to LGL.
  • ticket.created – Event ticket purchase (may duplicate or complement transaction.succeeded; see Worker logic).
  • campaign.created / campaign.updated – Used to refresh campaign cache for Mappings.

Payload (conceptual)

  • Transaction: id, amount, currency, campaign_id, supporter (name, email, phone, address), custom_fields, payment method, created_at.
  • Campaign: id, name, type (donation, ticket, peer_to_peer).

NOMA Sync uses: transaction id (idempotency givebutter_{id}), amount, campaign_id/campaign type (for mapping), supporter email/name/phone/address (constituent), custom_fields (LGL custom fields), payment method (gift type).


Square

Endpoint: POST /webhooks/square
Auth: HMAC signature in header; validated with SQUARE_WEBHOOK_SIGNATURE_KEY. Request body must be the raw JSON (no modification by proxy).

Events

  • order.created – New order. Synced when state is COMPLETED or OPEN with payment.
  • order.updated – Order changed. Worker may fetch full order from Square API; syncs only when state is COMPLETED or OPEN with payment.

Payload (conceptual)

Square often sends a notification object with merchant_id, type, event_id, created_at, and data containing object with order_id (and sometimes a small order snapshot). NOMA Sync uses order_id to fetch the full order (and customer if needed) via Square API.

Key fields (from full order)

  • order.id – Idempotency key square_order_{id}.
  • order.location_id – Used for location override mapping to LGL fund.
  • order.total_money – Gift amount (cents → dollars).
  • order.created_at – Gift date.
  • order.tenders – Payment type (CARD, CASH, etc.) mapped to LGL payment type.
  • order.customer_id – Fetched to get email/name for constituent; if missing, default constituent is used.

Mailchimp

Endpoint: POST /webhooks/mailchimp
Auth: Webhook secret (if MAILCHIMP_WEBHOOK_SECRET or equivalent is set).

Events

  • Unsubscribe – Member unsubscribed from a list. NOMA Sync finds constituent in LGL by email and updates tags (e.g. remove “Newsletter”) per tag rules.
  • Cleaned – Email cleaned (bounced/invalid). Similar handling: update or remove LGL tag.

Payload (conceptual)

  • type – unsubscribe, cleaned, etc.
  • data – list_id, email, email_id, merges (FNAME, LNAME), etc.

NOMA Sync uses: list_id (list mapping), email (constituent lookup in LGL), and applies tag rules from Mailchimp Settings.


Idempotency

Sourceexternal_id formatPurpose
Givebuttergivebutter_{transaction_id}Avoid duplicate gifts for same transaction
Squaresquare_order_{order_id}Avoid duplicate gifts; LGL also enforces external_id
MailchimpEvent-based (no gift)Audit only; logged to sync_log; duplicate events are safe

Retries

  • Givebutter – Check Givebutter docs for webhook retry policy. NOMA Sync runs backup polling every 15 minutes.
  • Square – Square retries failed webhooks (e.g. 5xx). NOMA Sync returns 200 on success or when event is skipped (idempotent).
  • Mailchimp – Check Mailchimp docs for retry. Return 200 quickly to avoid duplicate sends.