Skip to main content
Groups are how Users get organized into collections — teams, affinity groups, departmental cohorts, or any other stable grouping. Unlike Projects (which represent volunteer opportunities) or Project Dates (specific occurrences), Groups persist independently of any particular event. They’re long-lived “this person is part of this team” records. Groups are also the most write-heavy resource in the Volunteer API. The seven Group endpoints support full CRUD plus a dedicated member-management pattern — making Groups the canonical path for programmatically organizing volunteers.

The seven endpoints

These seven endpoints are the only write-heavy surface in the API. If your integration needs to organize Users into collections programmatically, Groups are the path.

The Group resource

The GroupResource schema documents these fields:
⚠️ Spec gap (audit #39): GroupResource.description reads "List of Groups" — a copy-paste error. The schema describes a single Group, not a list. The description will be corrected in a future spec revision.

Parent-child group hierarchy

Groups can have parent-child relationships: The parent_id field on each Group identifies its parent. The has_subgroups boolean tells you whether a Group is itself a parent. This lets the customer build organizational structures that match their actual team structure — a top-level “all volunteers” Group, regional sub-groups, and event-specific crews beneath those. For partner integrations:

Listing groups

cURL

Available filters

Note: the spec does not document page as a parameter on /groups, but the response uses the standard data/links/meta envelope. Pagination almost certainly works the same as other list endpoints — follow links.next.

Common list patterns

Top-level Groups only:
JavaScript
If the parent_id query parameter accepts a blank value to mean “null”, this could be done server-side; otherwise filter client-side. Children of a specific Group:
JavaScript
Build a full tree:
JavaScript
For very deep hierarchies this is cheaper than recursively fetching children for each parent — one pass through all Groups, then assemble in memory.

Fetching a single group

cURL
Returns the GroupResource for the specified ID wrapped in data.
JavaScript
The single-Group response doesn’t include the members — those come from GET /groups/{id}/members.

Creating a group

POST /groups creates a new Group. The request body accepts:
⚠️ Spec gap (audit #21): The POST /groups endpoint returns 200 OK on success, not 201 Created (the HTTP-conventional code for resource creation). Code should expect 200 for a successful Group create.
The members array in the request lets you populate the Group at creation time. Without it, the Group is created empty and you’d separately call PUT /groups/{id}/members to add members.

The moniker fields

VOMO Groups support custom monikers — display labels that override the default “member” and “subgroup” wording for that Group: When set, these labels appear in the VOMO admin UI in place of the generic terms. Useful for organizations with established team vocabulary.

Updating a group

PUT /groups/{id} is a full replacement — submit the entire Group’s data, not just the fields you want to change.
cURL
Body fields accepted on PUT /groups/{id}:
⚠️ Spec gap (audit #23): The PUT /groups/{id} request body description in the spec reads "Group to create" — a copy-paste error from the POST endpoint. The actual behavior is full-record update, not creation.
Notice that members is accepted on PUT /groups/{id} — meaning a single update call can change both the Group’s metadata AND its member list. This is convenient for full Group migrations. For partial updates (modify only the description, leave everything else alone), use the GET-then-PUT pattern:
JavaScript
The GET-then-PUT pattern adds a round-trip per update but avoids accidentally clearing fields by omission.

Deleting a group

cURL
⚠️ Spec gap (audit #22): The DELETE /groups/{id} endpoint documents a 200 OK response with no body, not the HTTP-conventional 204 No Content. Code should check for 200 (or any 2xx) as success.
Deletes are typically irreversible. Practical considerations:
JavaScript

Listing group members

cURL
Returns the User records who are members of the Group. The response uses the standard data/links/meta envelope; each member entry is a User-shaped object.
JavaScript
For Groups with many members, paginate the same way as other list endpoints.

Replacing group members

PUT /groups/{id}/members replaces the Group’s entire member list:
cURL
Request body:
⚠️ Spec gap (audit #24): The PUT /groups/{id}/members request body description in the spec reads "Group to create" — another copy-paste error. The actual behavior is member list replacement.

Replacement semantics

The PUT replaces the entire member list. Members not in the submitted array are removed from the Group. To add a single member to a Group without removing others, first GET the current members, then PUT the union:
JavaScript
The cost: every member change is a GET + PUT pair. For high-frequency membership changes, batch them — collect adds/removes over a window, then issue a single PUT with the final desired state.

Bulk roster sync

For partner integrations syncing an external roster (e.g., a corporate volunteer program tracking who’s eligible to participate), batch operations work well:
JavaScript
This single PUT correctly handles all three cases: members staying, members being added, and members being removed. The synchronization is atomic from the API’s perspective.

Common workflows

Build a Group from a query

For dynamically-built Groups (e.g., “all volunteers who participated in 2024”):
JavaScript
The Group is a snapshot — building it from a query doesn’t make it “self-updating.” For ongoing maintenance, re-run periodically.

Reflect external team structure in VOMO

For organizations with existing team structures in HR or other systems:
JavaScript
A common pattern for partner integrations whose customers want their internal structure reflected in VOMO.

Find Groups containing a specific User

There’s no direct “Groups for User” endpoint — you fetch the User’s group memberships through the User detail or by querying Groups and checking memberships:
JavaScript
This is N+1 — one call per Group. For accounts with many Groups, it can be expensive. Consider whether the User-detail response already contains the Group memberships you need.

A reference Groups client

JavaScript

Where to go next

Users

The User resource — Group members are Users.

Organizations and Org Family

The Organization hierarchy that Groups belong to.

Manage Groups and Members

The workflow-page walkthrough for Group management patterns.

The Volunteer Data Model

The full data model context for Groups.
Last modified on May 22, 2026