Skip to main content
A contact.status_changed event fires when a contact’s Contact Group (lifecycle stage) changes. Contact Groups in FPT are the canonical lifecycle enum:
IDGroupMeaning
1LeadsProspective customers — not yet engaged
2ProspectsActive interest, possibly in trial
3MembersPaying customers with active memberships
4Past MembersFormer customers, churned
5Non-membersActive in the system but not on a membership
6OtherCatch-all for non-standard cases
7StaffEmployees / trainers (separate from gym members)
When a contact transitions between these — like a lead converting to a member, or a member churning to past-member — this event fires with both the previous and new group IDs.

Payload

{
  "eventId":        "9f1c7e2a8c4d4b1b9e3f5a6d7c8b9a0e",
  "eventType":     "contact.status_changed",
  "eventTimestamp": "2026-06-10T23:45:00.123Z",
  "locationId":    1234,
  "organizationId": 5678,
  "apiVersion":    "v1",
  "data": {
    "contactId":        9876,
    "previousStatusId": 1,
    "newStatusId":      3
  }
}

Fields in data

FieldTypeDescription
contactIdnumberThe contact whose status changed.
previousStatusIdnumberThe Contact Group ID the contact was in BEFORE the change.
newStatusIdnumberThe Contact Group ID the contact is in AFTER the change.
Why “status” instead of “contact group”? Externally, “status” is the more universal term for a lifecycle stage. Internally FPT calls it Contact Group. The event name uses the partner-facing label; the table above documents the mapping.

What triggers it

  • Staff explicitly changes a contact’s group in the admin
  • An automation triggers a group change (e.g., “When trial ends → flip to Past Member”)
  • Billing lifecycle (e.g., “Member’s last payment failed and they churned → flip to Past Member”) — when the billing-driven flow eventually publishes its own events (v1.2), you may receive a payment.failed or membership.cancelled shortly before this
  • A contact-import flow assigns groups in bulk

Companion contact.updated

contact.status_changed always fires alongside contact.updated for the same contactId. They share the same change event but represent different abstractions:
  • contact.updated — “something on this contact changed, look it up”
  • contact.status_changed — “specifically the lifecycle group changed, here are the previous and new values”
If you subscribe to both, dedupe in your handler so you only act once per logical change.

Important: multiple rapid transitions get coalesced

If a contact’s status changes Lead → Prospect → Member in 200ms (rare but possible via automation chains), the previousStatusId you receive may be Lead and newStatusId may be Member — skipping Prospect entirely. The intermediate state isn’t lost in FPT’s database; it just doesn’t surface as a separate event. If you need to track every step, use FPT’s contact-history API (when released) rather than relying on this event being granular.

What you might do with this

  • Trigger a marketing automation in your platform when leads convert to members
  • Update analytics dashboards for conversion rate, churn rate, lifecycle funnel
  • Sales notifications — “your assigned lead just became a member”
  • Workflow rules — “if a Member becomes a Past Member, ask for feedback via survey”