Group Member Sync
This guide picks up where Group Onboarding leaves off. Once you have a group and know which plan_id to subscribe members to, you can submit the group’s roster via POST /v1/groups/{group_id}/members/sync. The endpoint accepts the complete current roster for one group, validates it, and queues it for asynchronous processing.
Before you begin, make sure you have a valid API key. See Authentication for details.
Submit a Member Sync
Send the complete current roster as an array of members:
A successful response is 202 Accepted with an acceptance receipt:
Keep the request_id. It’s how you’ll inspect the per-member results once processing finishes — there are no webhooks for this flow, so polling the sync request is the only way to know how each row was applied.
Per-Member Fields
Member sync replaces the group’s active roster. Any member previously synced into this group but omitted from the new payload will have their subscription ended and will be dropped from the group. This is not an append operation. Always submit the complete current roster.
Limits: Each reference_id must be unique within the payload. Contact your account manager before sending payloads larger than a few thousand rows.
See the Submit Group Member Sync endpoint for the full request and response schema.
What Happens Next
After your sync is accepted, Vitable processes each member asynchronously:
- Triage. Vitable compares the incoming
reference_idset against the members currently subscribed to your organization’s plan in this group.- References present in the payload but not currently subscribed → add
- References currently subscribed but not in the payload → remove
- References present in both → no-op (existing subscription preserved)
- Add. For each new reference, Vitable provisions (or re-uses an existing) account, attaches it to the group, and starts a plan subscription on the requested
plan_id. A new member can authenticate immediately via the passwordless flow — see Authentication. - Remove. For each missing reference, Vitable ends the member’s plan subscription. The member’s account is preserved so prior care history stays accessible; they simply are no longer subscribed.
- Complete. Per-member outcomes are recorded on the sync request as
results. Therequest_idreturned above identifies that record.
There are no webhooks for group member sync. Neither completion of the
batch nor success/failure of an individual member triggers an event. To verify
outcomes, poll the sync request endpoint and inspect the results payload.
Inspecting Results
Poll GET /v1/groups/{group_id}/members/sync/{request_id} to read the status of a previously-submitted sync:
While processing is in flight, completed_at and results are both null. Once processing finishes, completed_at is a timestamp and results is an object with three lists:
A member appearing in failures was not applied. The rest of the batch still processed normally; failures do not abort the sync.
Updating, Adding, and Removing Members
Subsequent syncs follow the same model — submit the complete current roster every time.
- Add a new member: include their record (with a new
reference_id) in the next sync. - Update an existing member: keep their
reference_idstable and submit the new values. Field-level updates are applied to the existing record. - Remove a member: omit their
reference_idfrom the next sync. Their subscription is ended; their account is preserved so prior care history stays accessible. - Re-add a removed member: include them again in a later sync. Their account is reused; a fresh subscription is started.
- Remove everyone: submit
{ "members": [] }.
Treat your reference_id as a stable, durable identifier for the member on
your side (e.g. your HRIS row ID). Changing it across syncs causes Vitable
to treat the row as a new member — ending the old subscription and starting a
new one with broken continuity.
Troubleshooting
400on submit — missing or invalid field: the payload failed synchronous validation. Common causes: a required address field missing,phonenot exactly 10 digits, invalidstatecode, duplicatereference_idwithin the payload, orplan_idthat isn’t a valid UUID. The response message lists every failing field.202accepted, but a member is infailureswith"Plan … not found": theplan_idfor that member is not linked to your organization. Re-checkGET /v1/plansfor the IDs you can use.202accepted, but a member is infailureswith"Member already has an active subscription!": the matched member already holds an active plan subscription under a different organization. Their existing subscription is preserved untouched; the sync rejects the add. Coordinate with the other organization to end their subscription before re-syncing.- Member added, but they can’t log in: account provisioning is asynchronous and continues briefly after the sync completes. If the passwordless flow returns “user not found” right after a sync, wait a few seconds and retry.
resultsis stillnulllong after submit: the worker may be processing a backlog. If it staysnullfor more than a few minutes on a small batch, contact Vitable support with therequest_id.
Related API Endpoints
POST /v1/groups/{group_id}/members/sync— Submit a member syncGET /v1/groups/{group_id}/members/sync/{request_id}— Retrieve a sync request’s status and results

