Headless Collaborator Groups
Managing collaborator groups and binding programs and distributors to them over REST from a headless frontend. The binding is set with a collaboratorGroupId field on the program or distributor, not a separate endpoint.
Requires Siren Plus
Last updated: June 7, 2026
A collaborator group is a named cluster of collaborators with a structure (flat, linear chain, or parent-child). Once a program or distributor is bound to a group, the upline cascade and downline cascade calcs walk the group on every qualifying engagement.
The admin UI manages all of this from the WordPress dashboard. When your provisioning lives in code, a headless onboarding flow, an external CRM sync, or an infrastructure-as-code setup, you do the same work over REST. This page covers the workflow and the auth framing. For the wire-level request and response shapes of every endpoint, see Collaborator Groups (REST).
Who this applies to
This is a fully headless concern. Group management is not referral tracking that you bolt onto a WordPress storefront. It is administrative provisioning, so it always runs server-side against the admin REST surface, regardless of how the rest of your site is wired.
Authentication
Every collaborator-group endpoint is an admin endpoint. None of them are public, unlike the collaborator submission endpoint covered on the collaborator applications page. Call them from a server-side runtime (an Astro server function, a Next.js route handler, or a serverless function) using a WordPress application password. Treat that password as a server-side secret and never ship it to the browser.
Capabilities matter here. Full create, read, update, and delete on the CollaboratorGroup resource is granted only to the administrator and siren_platform_manager roles. Mint the application password from a user in one of those roles. A token from a lower-privilege role will be rejected by the capability check before the handler runs.
The two halves of the workflow
Wiring a group into your payout structure is two separate jobs. Keep them straight, because they live at different endpoints.
- Manage the group itself. Create the group, set its structure, and reconcile its members. All of this happens under the
/collaborator-groupsbase. - Bind a program or distributor to the group. This does not happen under
/collaborator-groupsat all. You set a field on the program or distributor. The next section is the part most people miss.
Binding is a field, not an endpoint
A program or distributor does not store its group association on its own row, and there is no /bind endpoint. The binding lives in the shared wp_siren_configs table. You set it by including a collaboratorGroupId field in the body of a PUT (or POST) against the program or distributor itself:
PUT /programs/{id}
{
"collaboratorGroupId": 12
}
The distributor side is identical against its own resource:
PUT /distributors/{id}
{
"collaboratorGroupId": 12
}
A listener on the program or distributor action event writes the config row and broadcasts a ProgramBoundToCollaboratorGroup or DistributorBoundToCollaboratorGroup event. This runs synchronously inside the same save, so the binding is in place by the time the request returns, and a read-back of the program or distributor reflects it. Passing null, "", or 0 clears the binding, which deletes the config row (a cleared binding is indistinguishable from one that was never set) and broadcasts the matching ProgramUnboundFromCollaboratorGroup or DistributorUnboundFromCollaboratorGroup event. Each program or distributor can be bound to at most one group. The full config-row keying is in the REST reference.
A typical provisioning round trip
POST /collaborator-groups with name and structure. Optionally include the initial members in the same body. Siren returns the new group with its id.
Reconcile the roster with PUT /collaborator-groups/{id}/members, or add to it with POST. Each member's metadata carries its structure-specific data, like position for a linear chain.
PUT /programs/{id} or PUT /distributors/{id} with collaboratorGroupId set to the new group's id. This is the step that actually wires payouts to the group.
On the next qualifying engagement, the upline or downline cascade calc walks the bound group and credits peers per layer.
You can fold step 1 and step 2 together. POST /collaborator-groups accepts a members array in the create body, so a group and its full roster can be written in one request.
The ten endpoints at a glance
There are ten endpoints across the group surface. Nine manage the group and its members, one reads the structure registry, and the binding reuses the program and distributor endpoints you already have.
Group lifecycle:
GET /collaborator-groupslists groups. Thefieldsquery parameter is required.GET /collaborator-groups/{id}reads one group.POST /collaborator-groupscreates a group, optionally with its initial members.PUT /collaborator-groups/{id}updatesname,description, orstructure. Member changes do not go through this endpoint.DELETE /collaborator-groups/{id}deletes the group and cascades its member rows. It does not detach bindings, so a program or distributor bound to the group keeps itscollaboratorGroupIdpointing at the now-deleted group, and its cascade then fails closed and credits no one. In a teardown flow, clear the binding first (aPUTagainst the program or distributor withcollaboratorGroupIdset tonull), then delete the group.
Membership:
GET /collaborator-groups/{id}/memberslists the members of one group.POST /collaborator-groups/{id}/membersadds members. Idempotent, so collaborators already in the group are skipped.PUT /collaborator-groups/{id}/membersfull-replaces the roster, reconciling the group against the payload.DELETE /collaborator-groups/{id}/members/{collaboratorId}removes one member.
Structure registry:
GET /collaborator-groups/structureslists the installed structure resolvers and the walker capabilities each one advertises.
The structures endpoint is worth one note for headless callers. Its providedWalkerCapabilities field is what the admin calc picker reads to hide calc strategies a bound group cannot support. The cascade calcs need the hasLayer capability, which linearChain and parentChild provide and flat does not. That filter is a frontend convenience. The REST API does not enforce it, so a client that sets a cascade calc against a flat-bound program will persist successfully and then emit no credits at runtime. Since the API does not validate it, a headless flow should check this itself: before binding a program that uses a cascade calc, read GET /collaborator-groups/structures, find the group’s structure, and confirm its providedWalkerCapabilities include hasLayer. The same hazard applies after the fact, because a PUT /collaborator-groups/{id} that switches a bound group to flat strips the capability and leaves the program’s saved cascade crediting no one. See Why some calculation methods disappear for the picker behavior.
Changing structure after the fact
PUT /collaborator-groups/{id} can change a group’s structure, and it broadcasts CollaboratorGroupStructureChanged when it does. Per-member metadata is not migrated when the structure changes. Switching a flat group to linearChain leaves every member without a position, which the linear-chain resolver treats as position 0. If your provisioning flips a group’s structure, follow it with a PUT /collaborator-groups/{id}/members that supplies the metadata the new structure needs.
See also
- Collaborator Groups (REST): the wire shapes, field tables, and full request and response bodies for every endpoint on this page.
- What are collaborator groups: the operator-facing concept page.
- Choosing a collaborator group structure: when to use
flat,linearChain, orparentChild. - Create a collaborator group: the same surface from the admin UI.