Webhooks #

eCardWidget has two webhook families:

  1. ecard_shared — fires when an eCard is sent/shared (email, link, social). Configured once in the dashboard (Settings → Developers → Webhook URL). See eCard-shared webhook.
  2. Member-change webhooks — fire when your directory changes (member created / updated / deactivated / deleted). Subscribed via the API; signed and retried. See Member-change webhooks.

eCard-shared webhook #

Set a Webhook URL under Settings → Developers and click Save (blank disables it). eCardWidget sends a POST with header User-Agent: eCardWidget Hook whenever an eCard is shared. The body is a JSON array of one or more events:

[
  {
    "event_type": "ecard_shared",
    "type": "email",
    "sender_request_id": "rmmbps64tn8tyl5ghdft4",
    "ecardid": 14744,
    "widgetid": 4069,
    "vanity_id": "smcxzw64jky8tcg",
    "sender_name": "Sender",
    "sender_email": "[email protected]",
    "recipient_name": "Recipient",
    "recipient_email": "[email protected]",
    "personal_message": "<p>Thinking of you!</p>",
    "locale": "en",
    "scheduled_to_be_sent_at": "2026-03-12T15:49:25Z",
    "sent": false,
    "opened": false,
    "merge_tags": "",
    "override_props": ""
  }
]
  • type is the share method: email, facebook, twitter, linkedin, sms, whatsapp, etc.
  • sent is false for pending email sends (the hook fires before dispatch) and true for immediate share/social sends. Use scheduled_to_be_sent_at for the expected send time.
  • This is the same event behind the Zapier "eCard Sent via Email" trigger (Zapier).

Member-change webhooks #

Get notified when your directory changes — e.g. to push new hires, updates, or terminations back into another system. These are the same events that power the eCardWidget Zapier triggers.

Base path: /v2/api/pub/team-member-actions Auth: Authorization: Bearer <YOUR_API_KEY> (see getting-started).

Subscribe — POST /subscribe #

curl -X POST https://app.ecardwidget.com/v2/api/pub/team-member-actions/subscribe \
  -H "Authorization: Bearer $ECW_API_KEY" -H "Content-Type: application/json" \
  -d '{ "event_type": "team_member_updated", "hookUrl": "https://your-app.example.com/hooks/ecw" }'

Returns the subscription id:

{ "success": true, "data": { "id": "<subscription-id>" }, "messages": [] }

Unsubscribe — POST /unsubscribe #

curl -X POST https://app.ecardwidget.com/v2/api/pub/team-member-actions/unsubscribe \
  -H "Authorization: Bearer $ECW_API_KEY" -H "Content-Type: application/json" \
  -d '{ "id": "<subscription-id>" }'

Event types #

Event Fires when
team_member_created a member is added
team_member_updated a member materially changes (idempotent re-syncs do not fire)
team_member_deactivated a member is deactivated
team_member_deleted a member is permanently deleted

Delivery payload #

Each delivery is a JSON POST to your hookUrl:

{
  "event_id": "00000000-0000-0000-0000-000000000000",
  "event_type": "team_member_updated",
  "timestamp": "2026-01-01T09:00:00Z",
  "source": "api",
  "changed_fields": ["job_position"],
  "member": {
    "id": 123,
    "email": "[email protected]",
    "employee_id": "EMP-100",
    "first_name": "Grace",
    "last_name": "Hopper",
    "job_position": "Engineer",
    "departments": ["Engineering"],
    "date_of_birth": "1800-04-12",
    "hire_date": "2021-03-01",
    "profile_image_url": "",
    "disabled": 0,
    "updatedat": "2026-01-01T09:00:00Z"
  }
}
  • source — where the change came from: api, zapier, ui, or import.
  • changed_fields — present on team_member_updated; lists what changed.
  • Birthday years are privacy-masked (stored as year 1800).

Signing & reliability #

  • Deliveries are signed with your account's webhook signing secret: X-ECW-Signature: sha256=<hmac> (HMAC-SHA256 of the raw request body). Verify it before trusting a payload.
  • Failed deliveries are retried automatically.
  • Use event_id to de-duplicate (a retry reuses the same id).
  • The bulk spreadsheet importer does not emit these events — they're for ongoing per-record changes.

Loop awareness #

If you both write to ECW (via upsert) and listen for changes, use the source field to avoid feedback loops (e.g. ignore events your own integration caused).


Documentation