Group Member Sync
Submit your member roster for a group. Vitable provisions accounts and starts plan subscriptions asynchronously.
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
Section titled “Submit a Member Sync”Send the complete current roster as an array of members:
curl -X POST https://api.vitablehealth.com/v1/groups/{group_id}/members/sync \ -H "Authorization: Bearer $VITABLE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "members": [ { "reference_id": "mem-001", "first_name": "Maria", "last_name": "Garcia", "date_of_birth": "1990-05-15", "phone": "5555550101", "plan_id": "pln_aBcDeFgHiJkLmNoPqRsTuV", "address": { "address_line_1": "123 Main Street", "city": "Pittsburgh", "state": "PA", "zipcode": "15222" }, "email": "maria@beanworks.example.com" }, { "reference_id": "mem-002", "first_name": "James", "last_name": "Chen", "date_of_birth": "1985-11-22", "phone": "5555550102", "plan_id": "pln_aBcDeFgHiJkLmNoPqRsTuV", "address": { "address_line_1": "456 Oak Avenue", "address_line_2": "Apt 4B", "city": "Pittsburgh", "state": "PA", "zipcode": "15201" } } ] }'A successful response is 202 Accepted with an acceptance receipt:
{ "data": { "request_id": "grpmsr_pQr456sTu789vWxYzAbCd", "group_id": "grp_zYxWvUtSrQpOnMlKjIhGfE", "accepted_at": "2026-03-25T14:30:00+00:00" }}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
Section titled “Per-Member Fields”| Field | Type | Required | Rules |
|---|---|---|---|
reference_id | string | Yes | 1–255 chars. Must be unique within the payload. Used to match existing members across syncs. |
first_name | string | Yes | Max 255 chars. |
last_name | string | Yes | Max 255 chars. |
date_of_birth | string | Yes | ISO 8601 date (e.g. 1990-05-15). |
phone | string | Yes | 10-digit US number, digits only (5551234567). |
plan_id | string | Yes | A pln_ ID available to your organization. See Group Onboarding — Step 1. |
address | object | Yes | See address fields below. |
address.address_line_1 | string | Yes | Max 255 chars. |
address.address_line_2 | string | No | Max 255 chars. |
address.city | string | Yes | Max 255 chars. |
address.state | string | Yes | 2-letter US state or territory code (PA, CA, etc.). |
address.zipcode | string | Yes | US ZIP. |
email | string | No | Valid email address. |
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
Section titled “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.
Inspecting Results
Section titled “Inspecting Results”Poll GET /v1/groups/{group_id}/members/sync/{request_id} to read the status of a previously-submitted sync:
curl -X GET https://api.vitablehealth.com/v1/groups/{group_id}/members/sync/{request_id} \ -H "Authorization: Bearer $VITABLE_API_KEY"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:
{ "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"], "removed_group_member_ids": [], "failures": [ { "reference_id": "mem-003", "operation": "add", "reason": "Plan pln_… not found" } ] } }}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
Section titled “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": [] }.
Troubleshooting
Section titled “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
Section titled “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