Skip to content
Embedded Care
Concepts

Member Sync

How member sync works under the hood — the replacement model, reference matching, async processing, and how to read the results.

Member sync is the single endpoint you use to add, update, and remove members within a group. You send the complete current roster for one group, and Vitable reconciles the existing membership against what you submitted: anything new is added, anything missing is removed, anything unchanged is left alone.

You send one POST /v1/groups/{group_id}/members/sync request containing your members, and Vitable processes them asynchronously. The HTTP response is an acceptance receipt — not the final result. Final outcomes appear on the sync request itself once processing completes.

This page covers the replacement model, how members are matched across syncs, the async flow, and how to read results — including partial failures.

Every sync replaces the set of members currently subscribed to the group’s plans. Vitable treats the payload as the new truth and reconciles by reference_id:

What you submitWhat Vitable does
A reference_id not currently subscribed in the groupAdd — provision/attach the member, start a plan subscription
A reference_id currently subscribed in the groupNo-op — leave the existing subscription alone (field-level updates to the member record are applied)
A reference_id currently subscribed in the group but missing from the payloadRemove — end the plan subscription

An empty members: [] is a valid sync. It removes everyone in the group.

reference_id is your stable, partner-owned identifier for a member. Vitable uses it to recognize the same person across syncs.

Within a single payload, every reference_id must be unique. Sending the same reference_id twice in one sync fails synchronous validation with HTTP 400.

When a new reference_id is added, Vitable will re-use an existing person record if the contact details match someone it already knows — typically by email and date of birth. The member retains their prior care history; only the group membership and the plan subscription are new.

sequenceDiagram
    participant P as Partner
    participant V as Vitable API
    P->>V: POST /v1/groups/{id}/members/sync (N members)
    V-->>P: 202 { data: { request_id, group_id, accepted_at } }
    Note over V: Triage: classify each member as add / remove / unchanged
    Note over V: Async processing per member
    P->>V: GET /v1/groups/{id}/members/sync/{request_id}
    V-->>P: 200 { data: { results: { added, removed, failures } } }

Flow summary:

  1. You submit a roster for one group.
  2. Vitable validates the payload structure and returns 202 with a request_id (grpmsr_…) and accepted_at.
  3. Vitable reconciles your payload against the group’s current roster and processes each add/remove asynchronously.
  4. When processing is complete, the sync request’s results field is populated with per-member outcomes.

To inspect the outcome of a sync, call:

Terminal window
curl -X GET https://api.vitablehealth.com/v1/groups/{group_id}/members/sync/{request_id} \
-H "Authorization: Bearer $VITABLE_API_KEY"

Until processing finishes, completed_at and results are both null. Once processing completes, completed_at is a timestamp and results is an object with three lists:

{
"data": {
"request_id": "grpmsr_pQr456sTu789vWxYzAbCd",
"group_id": "grp_zYxWvUtSrQpOnMlKjIhGfE",
"accepted_at": "2026-03-25T14:30:00+00:00",
"completed_at": "2026-03-25T14:30:08+00:00",
"results": {
"added_group_member_ids": [
"grpmbr_lMn345oPq678rSt",
"grpmbr_aBc123dEf456gHi"
],
"removed_group_member_ids": ["grpmbr_xYz789uVw012aBc"],
"failures": [
{
"reference_id": "mem-099",
"operation": "add",
"reason": "Plan pln_… not found"
}
]
}
}
}
FieldMeaning
added_group_member_idsMembers newly subscribed to the group’s plan. Each ID is prefixed grpmbr_.
removed_group_member_idsMembers whose plan subscriptions were ended.
failuresPer-member errors. A member listed here was not applied — the rest of the batch processed normally.

Each failure entry includes the reference_id you submitted, the operation Vitable was attempting (add or remove), and a human-readable reason.

A sync that matches the group’s existing roster exactly is a no-op — no members are added, none are removed, no failures are recorded. This makes it safe to re-submit the same roster:

  • After a network error, if you don’t know whether the previous request landed, you can safely resubmit.
  • On a schedule, you can run periodic full-roster syncs (e.g. nightly) to keep Vitable in lockstep with your source of truth.

The only thing a re-submitted sync changes is the audit trail: every accepted submission creates a new request_id, even if zero members move.

A sync that is accepted (202) does not guarantee every member processes successfully. The two most common reasons a single member ends up in failures are:

  • plan_id not available to your organization. The plan UUID isn’t linked to your org. Failures cite "Plan {id} not found". Re-check GET /v1/plans for the IDs you can use.
  • Member already has an active subscription elsewhere. The matched member holds an active plan subscription under a different organization. Vitable preserves their existing subscription untouched and rejects the add with "Member already has an active subscription!". Coordinate with the other organization to end the existing subscription before re-syncing.

Other rows in the same sync are unaffected. A failure list with one entry means one member didn’t apply; the other N–1 did.

These errors come back immediately as HTTP 400 — no processing occurs:

  • A required field is missing on any member (reference_id, first_name, last_name, date_of_birth, phone, plan_id, address).
  • phone is not a 10-digit US number.
  • address is missing a required field (address_line_1, city, state, zipcode) or state is not a valid 2-letter US state/territory code.
  • plan_id is not a UUID.
  • Two members share the same reference_id within the payload.
  • The group_id in the URL is malformed or does not belong to your organization.

The 400 response lists every failing field. Fix and resubmit; nothing changes in the group until a 202 is returned.

  • Groups — what a group is and how to organize them.
  • Member Lifecycle — what happens to a member after they’re synced.