Groups
This document will help you create groups and organisations, manager their members and accept or reject invites.
AI-assisted, human-approvednovem uses AI to review and keep our documentation up to date.
Overview
Groups control how resources are shared among users. A group belongs to an individual user or an organisation. This reference covers membership, roles, invitations, and group profiles.
The examples use fictional users and the fictional organisation acme.
Groups
Groups can either belong to a user and be a user group or
an organisation and be an org group.
A user group consists of an @ followed by a username, then a ~ and a group name. An organisation group consists of a + followed by an organisation name, then a ~ and a group name.
Usernames, organisation names, and group names cannot contain spaces.
User groups are created by PUTing a group name under the /admin/groups/ folder and
organisations by PUTing an organisation name under the /admin/orgs/ folder.
To add a user to a group you simply PUT the username in the
/admin/groups/<group_name>/roles/<ROLE>/ folder where <ROLE> is one of
founders, admins, superusers or members.
The user creating a group or organisation is automatically given the founder role.
The groups of which you are a member are listed under /admin/groups, keyed by
their group slug (not the display name). Org groups you can see are also
surfaced under /orgs/<org>/groups.
User Groups
User groups are the unit of sharing for individuals. Create one by PUTting a
group name under your /admin/groups/ folder; you become its founder
automatically.
PUT /v1/admin/groups/analysts
A user group is referenced elsewhere, for example when sharing a visual, as
@username~groupname (e.g. @alice~analysts).
Inviting users
Add a member by PUTting their username into one of the group's role folders.
The roles, from most to least privileged, are founders, admins,
superusers and members.
PUT /v1/admin/groups/analysts/roles/members/bob
The invited user receives an invitation they must accept before the membership
becomes active; until then they show in the role listing with an I- prefix
(the same pending marker used for social connections).
Accepting or declining an invite
Pending invites are listed under the invited user's /admin/invites/ folder,
keyed by the group reference (@alice~analysts). Each invite holds a single
accept endpoint; POST yes to it to accept, or no to decline:
GET /v1/admin/invites -- list pending invites
POST /v1/admin/invites/@alice~analysts/accept -- body: yes (or no to decline)
curl -X POST -H "Authorization: Bearer $NOVEM_TOKEN" \
-H "Content-Type: text/plain" \
--data "yes" \
https://api.novem.io/v1/admin/invites/@alice~analysts/accept
Note: Text bodies must be sent as text/plain. curl's --data flag
defaults to application/x-www-form-urlencoded, which the API rejects —
always pass -H "Content-Type: text/plain" alongside it.
Promoting users
Changing a member's role is the same PUT, into a different role folder — to
promote bob from member to admin:
PUT /v1/admin/groups/analysts/roles/admins/bob
Removing users
DELETE the user from the role folder to revoke their membership. The role
folder must be the one the user actually holds — deleting bob from
roles/members/ when he is an admin removes nothing and answers 404.
DELETE /v1/admin/groups/analysts/roles/members/bob
Leaving a group or organisation
An accepted member may delete their own role, including after a subscription downgrade. The last accepted founder must arrange a replacement before leaving. The webapp provides a confirmed leave action in the group or organisation header.
Leaving an organisation removes your organisation role only. Your memberships in its groups remain, so you can still see the organisation and access content through those groups. Leave each group separately to remove those memberships. Content may remain reachable through other shares or public access.
Who may promote and remove whom
Role management needs superuser or above, and reaches your own rank and
below. A superuser may add and remove members and other superusers; an
admin may do the same to admins; a founder to founders. Nobody can promote
someone above their own rank, and nobody can remove or demote someone above
it — so an admin cannot appoint a founder, and a superuser cannot remove an
admin.
Two further restrictions apply:
- A group always keeps a founder. The last remaining founder can neither be removed nor demoted, including by themselves. Appoint another founder first.
- A user group's founder is fixed. It is set when the group is created and cannot be granted, changed or removed afterwards. Organisation and org-group founders have no such restriction.
Revoking an invite you sent
An invite is pending until the invitee accepts it, and whoever sent it can always withdraw it in that window — even if you have since been demoted, and even if someone more senior has raised the role the invite carries. Use the role folder the invite currently names:
DELETE /v1/admin/groups/analysts/roles/admins/bob
Once bob accepts, removing the membership follows the rank rules above.
You can withdraw your own pending invitations while you remain in the group.
Before leaving, withdraw them or ask a remaining admin to manage them.
Organisations
Organisations are shared parents for groups that belong to a company or team
rather than a single user. Create one by PUTting an organisation name under
/admin/orgs/; as with groups, the creator becomes the founder.
PUT /v1/admin/orgs/acme
Note: Two constraints apply, both enforced by the API: only
organisation accounts can create organisations (a regular account gets a
403), and each account can create exactly one.
Organisation-level roles (membership of the organisation itself) are managed
under /admin/orgs/<org>/roles/<role>/<user> using the same four role folders.
Organisation Groups
An organisation's groups live under the org and are referenced as
+orgname~groupname, e.g. +acme~research. They are created and have their
members managed exactly like user groups, one level deeper under the org:
# create the research group under the acme org
PUT /v1/admin/orgs/acme/groups/research
# add a member
PUT /v1/admin/orgs/acme/groups/research/roles/members/bob
Organisation admins see every group
An organisation admin or founder has oversight of every group under the
organisation. All of the org's groups appear in their views — the
/v1/orgs/:org/groups listing, the organisation's groups in GraphQL, and the
dashboard — each with its profile and full member roster, even for groups the
admin has not joined. A superuser is an in-group moderator role and carries
no org-wide oversight; like a regular organisation member, they see only the
groups they belong to.
Oversight is read-only on its own. To administer a group — invite or remove
members, edit its profile or options — an org admin must hold a role in the
group itself, and may claim one directly, without waiting for an invite, by
PUTting their own username into a role folder:
# an org admin claims the admin role on a group under their org
PUT /v1/admin/orgs/acme/groups/research/roles/admins/alice
The role takes effect immediately, with no invitation to accept, because the
admin is exercising the organisation's own authority. This is the intended way
to take over a group whose previous administrator has left. Until a role is
claimed the group's role sub-resource returns nothing, since the admin holds
no role in it yet.
Inbound e-mail address
An org group can have its own inbound e-mail address. Mail sent to it
triggers a run of every job
shared with the group; it is not delivered to the group's members. The address
is computed and read-only; it takes the form <group>@<org>.<org-mail-domain>,
for example research@acme.<org-mail-domain> (the domain suffix is configured
per environment).
Each trigger must have exactly one unambiguous From address and authenticate
that sender with aligned DKIM or envelope SPF. A message that fails this check
is retained as inbound mail for diagnosis but starts no job and receives no
reply. When a run is admitted, its result is sent to the From address and
copied to each To or Cc recipient who holds a verified novem e-mail address
and may run the job themselves. A failed run is reported to the sender alone.
Other recipients and Reply-To get nothing, and a Bcc recipient is not
visible to novem, so it gets no copy either.
The address exists only when both of these hold:
- the parent organisation has its mail subdomain enabled, and
- the group accepts inbound mail.
Read it from the group's email sub-resource. When the group is not
mail-enabled the value is empty:
GET /v1/orgs/acme/groups/research/email -- plain text, "" if not mail-enabled
Any member of the group (member, superuser, admin or founder) can read
it. The same value is returned as the email field on the group's info object
and as the email field on Group in GraphQL; both are null when the group
is not mail-enabled.
Group & organisation pages
A group or org has a profile, the page people see at its public URL. It works
like your own profile: a profile folder
with text fields and imagery, all written with POST (or PUT/DELETE for
imagery) by a founder or admin.
| Verb | Path | Description |
|---|---|---|
GET | .../profile | The profile folder |
POST / GET / DELETE | .../profile/name | Display name |
POST / GET / DELETE | .../profile/description | Description, rendered as markdown |
POST / GET / DELETE | .../profile/picture/image | Avatar |
POST / GET / DELETE | .../profile/picture/banner | Banner |
POST / GET / DELETE | .../profile/picture/mask | Avatar crop (x,y,r) |
.../ is /admin/groups/:group for a user group or
/admin/orgs/:org/groups/:group for an org group; orgs themselves expose the
same profile tree at /admin/orgs/:org.
Organisation workflow activity
GET /v1/orgs/:org/profile/stats/activity returns a daily workflow-run
series for the authenticated caller's readable shares within an organisation.
Despite living under the read-oriented /orgs tree, this is member activity,
not public organisation analytics.
The caller must hold an accepted member, superuser, admin or founder
role either directly on the named organisation or on one of its child org
groups. A pending role does not qualify; an unknown organisation or a caller
without that relevance receives 404. The activity itself is narrower than
that relevance check: it includes only distinct jobs carrying a readable
({r}) share to a child org group under the named organisation in which the
caller is an accepted member. A job shared through more than one qualifying
group is counted once.
There is no parent-organisation content inheritance. A direct organisation member or administrator who belongs to none of its child groups can reach the endpoint but receives a zero-filled series. Public-only jobs, jobs shared directly with the caller, jobs shared through user groups or another organisation, owned-but-unshared jobs, jobs reachable only through a pending group membership and shares without read permission are not included.
Only top-level runs are counted; nested child runs are excluded. The response is a dense chronological series ending on the current UTC day and capped at the most recent 371 UTC calendar days. Days without matching runs are present with zero counts.
The default response is a plain-text table with flat columns. Send
Accept: application/json to receive the same data as an array:
curl -H "Authorization: Bearer $NOVEM_TOKEN" \
-H "Accept: application/json" \
https://api.novem.io/v1/orgs/acme/profile/stats/activity
[
{
"day": "2026-08-17",
"views": 0,
"vdes_created": 0,
"mails_sent": 0,
"social": 0,
"jobs": {
"total": 3,
"trigger": {
"api": 1,
"schedule": 1,
"email": 1
},
"status": {
"success": 2,
"failed": 1
}
}
}
]
jobs.total is the total number of included top-level runs for the day;
jobs.trigger and jobs.status provide the corresponding trigger and outcome
breakdowns. The views, vdes_created, mails_sent and social fields are
currently always zero. They are retained so this endpoint has the same
ActivityDay response shape as profile activity.
Visibility options
The profile/options folder holds boolean toggles
(yes/no, default no), again founder/admin only:
| Option | Effect |
|---|---|
public | Whether people outside the group/org can find it and see its profile |
show_profile | Show the profile page (stored, not yet enforced) |
show_description | Show the description on it (stored, not yet enforced) |
show_members | Show the member list (stored, not yet enforced) |
is_open | Let users join without an invite (stored, not yet enforced) |
Only public changes what anyone can see or do today. The other four are
stored and returned by the GraphQL groups query, but nothing acts on them
yet: setting show_members to no does not hide the member list, and setting
is_open to yes does not let anyone join without an invite.
In the webapp, the Visibility switch on an organisation's, org group's or
user group's Admin tab sets public. It is shown to the founders and
admins who may write it, which for an org group includes the parent
organisation's founders and admins. Going public shows the profile to everyone:
name, summary, description, picture, banner and the creator's username. For an
org group it also shows the parent organisation's name, even when the
organisation itself is private, and the group's workflow email address if it
receives workflow email. It does not publish the content shared with the group, and the member
list stays visible only to people in it.
Organisations also have two nullable identity colours. These are small dashboard accents, separate from the organisation's full visualisation theme:
| Verb | Path | Description |
|---|---|---|
GET / POST / DELETE | /admin/orgs/:org/profile/options/primary_color | Primary identity colour, used for organisation identity and aggregate activity |
GET / POST / DELETE | /admin/orgs/:org/profile/options/secondary_color | Optional secondary accent |
POST takes a plain-text CSS hex colour in strict #RRGGBB form: a leading
# followed by exactly six hexadecimal digits. A trailing editor line ending
is removed; other surrounding whitespace is invalid. Hexadecimal letters may
be upper- or lowercase and are preserved. Malformed values return 400
without replacing the stored colour. The management leaves are available on
premium and enterprise plans; reading or writing them requires an accepted
organisation founder or admin role.
DELETE idempotently resets the selected colour to null and returns an empty
plain-text response. A GET on an unset colour returns an empty value; the
organisation GraphQL fields and user_info.primary_org overview fields return
null. When the primary colour is null, dashboard surfaces use the standard
Novem colour. A null secondary colour means that no organisation-specific
secondary accent is configured.
Note: for organisations and org groups the show_* options
require a premium subscription. User-group options are available on all
plans.
Groups and orgs also carry comment threads at
.../threads/*, on the same paid-to-write, free-to-read terms as the rest of
the platform.
Org themes (the branding applied to a whole organisation's content) are documented separately under org themes.
Browsing groups & orgs
The management endpoints above live under /admin. The read-oriented views are
public (subject to the visibility options):
| Path | Description |
|---|---|
/v1/orgs | Organisations visible to you |
/v1/orgs/:org | An organisation — description and groups |
/v1/orgs/:org/groups | The org's groups — all of them for an org admin, otherwise those you belong to |
/v1/orgs/:org/groups/:group | A group — name, description, profile, role (your role in it, empty until you hold one) and shared content |
/v1/orgs/:org/profile/stats/activity | Daily top-level runs for jobs shared readably through your child org groups |
/v1/users/:user/groups | A user's groups visible to you |
/v1/o/:org | The org FQNP alias — card, banner, img, and the org's visuals under p / g / m / d / v |