Groups

Create a named group of Payees, add and remove members one at a time or in bulk, and handle the ETags that group changes require.

A Group is a named set of Payees, such as "California nurses" or "Q4 inspection crew". This page shows you how to create a group, add and remove Payees, and delete a group. Groups replace V1 collaborator groups.

What changed from V1

In V1, a collaborator group carried eligibility requirements, and adding a collaborator to a group sent them those requirements. In V3 those jobs are split:

  • Groups organize Payees into cohorts.
  • Engagements carry requirements. To make a set of Payees sign a document or upload a license, attach the requirement to an Engagement and assign those Payees to it. See Requirements and eligibility.
V1V3
POST /payments/collaborator-groupPOST /v3/payments/groups
eligibilityRequirements on the grouprequirementDefinitionIds on an Engagement
PATCH /payments/collaborator/{id}/add-group/{groupId}POST /v3/payments/groups/{groupId}/members
collaboratorGroupId on the inviteA separate add-member call after creating the Payee

The group resource

FieldWhat it means
idThe group ID.
nameRequired on create.
typeAlways Payee. Required on create.
description, externalId, metadataYour labels and IDs. A duplicate externalId returns 409 ResourceConflict.
statusActive or Deleted.
memberCountHow many Payees are in the group.
membershipVersionA counter that goes up every time membership changes. It's what the group's ETag is built from.
accountIdYour Account. Every member must be a Payee owned by this Account.

Create a group

curl -X POST https://api.wingspan.app/v3/payments/groups \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "California nurses",
    "type": "Payee",
    "description": "RNs licensed in CA",
    "externalId": "GRP-CA-RN"
  }'
// 201 Created (trimmed)
{
  "id": "wug8qBmy8cBW3YJNjBDrHD",
  "name": "California nurses",
  "type": "Payee",
  "status": "Active",
  "memberCount": 0,
  "membershipVersion": 0,
  "events": { "createdAt": "2026-09-24T15:40:00Z" }
}

Changes require If-Match

Updating a group, deleting it, and adding or removing members all require an If-Match header with the group's current ETag. This stops two people from changing membership at the same time and silently overwriting each other.

Get the ETag from GET /v3/payments/groups/{groupId} or from the response to your last change:

curl -i https://api.wingspan.app/v3/payments/groups/wug8qBmy8cBW3YJNjBDrHD \
  -H "Authorization: Bearer $WINGSPAN_TOKEN"
# ETag: "..."

If the group changed since you read it, you get 412 with code: PreconditionFailed. Read the group again and retry with the new ETag. See Concurrency and ETags.

Add a payee

curl -X POST https://api.wingspan.app/v3/payments/groups/wug8qBmy8cBW3YJNjBDrHD/members \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Content-Type: application/json" \
  -H "If-Match: $GROUP_ETAG" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "payeeId": "M9ISYbzJElXs4zIHv76rjT" }'
// 201 Created
{
  "id": "W6uJfLU9dBxmBI6Eu9uoS8",
  "accountId": "z9uv0jPAxTqSLs5UKwv1DE",
  "groupId": "wug8qBmy8cBW3YJNjBDrHD",
  "payeeId": "M9ISYbzJElXs4zIHv76rjT",
  "status": "Active",
  "membershipVersion": 1,
  "events": { "createdAt": "2026-09-24T15:41:12Z" }
}

Save the member id. You need it to remove the Payee later.

This call can also return 202 with an AsyncOperation when adding the member takes longer to process. Poll GET /v3/platform/operations/{operationId} from the Location header, pacing on Retry-After. See Async operations.

Changing group membership is a sensitive action, so it requires a person's own session with recent multi-factor authentication. Without it you get 403 with code: StepUpMfaRequired. The same applies to removing members, bulk adds, and deleting a group.

Add up to 100 payees at once

POST /v3/payments/groups/{groupId}/members/bulk adds 1 to 100 Payees. The whole request is validated first and applied in one transaction: either every Payee is added (or re-added, if previously removed) or none are.

curl -X POST https://api.wingspan.app/v3/payments/groups/wug8qBmy8cBW3YJNjBDrHD/members/bulk \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Content-Type: application/json" \
  -H "If-Match: $GROUP_ETAG" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "members": [
      { "payeeId": "M9ISYbzJElXs4zIHv76rjT" },
      { "payeeId": "JDft9g7rxT3I8yuWXpMBg6" }
    ]
  }'

This returns 202 with an AsyncOperation. Poll it until status is terminal. The GroupMember.Created webhook event is available for subscription and fires for each member added.

Remove a payee

curl -X DELETE https://api.wingspan.app/v3/payments/groups/wug8qBmy8cBW3YJNjBDrHD/members/W6uJfLU9dBxmBI6Eu9uoS8 \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "If-Match: $GROUP_ETAG"

The path uses the member id from the add response, not the payeeId. It returns 204.

Update, list, and delete groups

The V3 API doesn't have an endpoint that lists a group's members yet. Keep the member id values from your add responses if you need to remove Payees later.

What can go wrong

StatuscodeWhat it means
403StepUpMfaRequiredThe session needs recent multi-factor authentication for this change.
404ResourceNotFoundThe group, Payee, or member doesn't exist in your Account.
409ResourceConflict or InvalidStateTransitionDuplicate externalId, or deleting a group that still has members.
412PreconditionFailedYour If-Match ETag is out of date. Read the group and retry.
422ValidationErrorA required field is missing, or members is empty or over 100.

Related


Did this page help you?