Bring your team in

Invite writers, reviewers and admins, and give each of them exactly the access they need.

Embed
Preview of the card
<a href="https://forumulate.com/guides/invite-your-team"><img src="https://forumulate.com/guides/_api/public/orgs/046a9bc0-d530-43ae-9bae-af7945008cda/spaces/36aa4df0-1e95-4cef-8ae9-795169441345/pages/41dd9f6e-0b74-40ab-a812-ab01d112158d/social-card.svg?v=3e7ae33eec8b" alt="Bring your team in" width="600" height="315"></a>

Everyone who writes has an account, and nobody has more access than their job needs.

Before you start

  • You are an owner or an admin of the organization.

Steps

  1. Open Members at /o/{orgId}/members and invite by email. An invitation names the role it grants.

  2. Pick the role. There are seven, from most to least privileged:

    Role

    What it can do

    Owner

    Everything, including billing and deleting the organization.

    Admin

    Settings, members, roles and spaces. Not billing.

    Maintainer

    Writes and publishes documentation, and manages a space's structure.

    Editor

    Writes and publishes in the content surfaces — blog, changelog, roadmap.

    Moderator

    Moderates the community: flags, locks, moves, suspensions.

    Member

    Takes part — posts, comments, votes.

    Guest

    Read-only.

    There is no "Viewer". The read-only role is Guest. (An earlier version of this page named Viewer, listed four of the seven, and described Editor as the docs role; all three were wrong.)

  3. Grant at the right scope. A role given at the organization applies everywhere; a role given on one space applies only there, and a space grant can narrow an organization grant as well as widen it. A deny always wins over an allow, at any level.

  4. If you need something that is not one of the seven, build a custom role at /o/{orgId}/roles out of individual capabilities, and use groups at /o/{orgId}/groups to grant it to several people at once.

Granting a role to a whole group

Instead of granting a role person by person, grant it to a group. This needs org.manage_roles.

POST /orgs/{orgId}/group-grants
{
  "groupId": "<groupId>",
  "role": "MODERATOR",
  "spaceId": "<spaceId>",
  "effect": "ALLOW"
}

Leave spaceId out (or null) for an organization-wide grant; give it to confine the grant to one space. effect is ALLOW (the default) or DENY, and a deny always wins. customRoleId grants one of your custom roles instead of a built-in one. You cannot grant a role with capabilities you lack, and only an owner can grant ownership; both are 403. An unknown group or space is a 404. Create answers { "grant": ... }.

GET /orgs/{orgId}/group-grants lists grants and narrows with ?spaceId= and ?groupId=. DELETE /orgs/{orgId}/group-grants/{id} revokes one.

A member's group title and primary group

A member can choose how groups present them. A group (or a badge) may carry a title, and a member may adopt one of the titles they have been granted and pick which of their groups is their primary group, whose colour and flair render next to their name. Any signed-in member can do this for themselves; it needs only org.read.

GET /orgs/{orgId}/group-identity
# { "current": { "title", "primaryGroupId" },
#   "adoptableTitles": [ ... ], "primaryGroups": [ { "id", "name" } ] }

PUT /orgs/{orgId}/group-identity
{ "title": "Core team", "primaryGroupId": "<groupId>" }

Send null to clear either. A title the member has not been granted is a 422 ("That title is not one you have been granted"), and so is a primary group they do not belong to.

Asking what you may do in a space

GET /orgs/{orgId}/spaces/{spaceId}/my-access (needs space.read) answers { "canEdit": boolean, "canModerate": boolean } for the caller: whether they hold docs.write and forum.moderate there. Use it to decide whether to show an "Edit this page" or moderation control. A role does not imply the answer (a plain member can read a space but cannot edit it), so ask rather than guess from the role.

Requiring SSO

Connect your identity provider at /o/{orgId}/sso and turn on Require SSO there. After that, members sign in through your provider and a password is no longer an option.

That path is the one to use. There is no "Settings → Authentication" screen — the organization console has no authentication route at all. The three ways this was previously described sent people looking for a page that does not exist.

Reader sign-in is a different setting in a different place. SSO at /o/{orgId}/sso governs the people who write; who may read a space is configured separately — see Reader sign-in.

Where each control lives

What

Where

Invite, remove, change a role

/o/{orgId}/members

Custom roles

/o/{orgId}/roles

Groups, and grants to a group

/o/{orgId}/groups

Staff SSO and Require SSO

/o/{orgId}/sso

Who may read a space

The space's Settings fold → Access

Reader sign-in providers

The organization's reader sign-in settings

Audit log

/o/{orgId}/settings

How to know it worked

The invited person appears under Members with the role you chose, and their first sign-in lands in your organization rather than in a new one of their own.

If they land in an empty organization of their own, they signed up fresh instead of accepting the invitation — delete that organization and have them use the link in the email.

What's next

In the API

Every operation below is also reachable from the other surfaces without a dedicated command. forumulate api <Operation> calls it from the CLI, the JavaScript SDK has a typed method for each one (the last column names it; the Python and Go clients are generated from the same spec), and an agent reaches the organization-scoped ones through the MCP call_api tool. Where a CLI command or MCP tool exists too, the last column names it. Operation names link to the API reference.

Badge Query Grant

Operation

Request

What it does

Shortcuts

BadgeQueryGrant_list

GET /orgs/{orgId}/admin/badge-query-grants

List badge query grants in an organization

client.grants.badgeQuery.list()

BadgeQueryGrant_create

POST /orgs/{orgId}/admin/badge-query-grants

Create a badge query grant in an organization

client.grants.badgeQuery.create()

BadgeQueryGrant_update

PATCH /orgs/{orgId}/admin/badge-query-grants/{ruleId}

Update the badge query grant

client.grants.badgeQuery.update()

BadgeQueryGrant_remove

DELETE /orgs/{orgId}/admin/badge-query-grants/{ruleId}

Delete the badge query grant

client.grants.badgeQuery.remove()

BadgeQueryGrant_runOne

POST /orgs/{orgId}/admin/badge-query-grants/{ruleId}/run

Run the badge query grant

client.grants.badgeQuery.runOne()

BadgeQueryGrant_runAll

POST /orgs/{orgId}/admin/badge-query-grants/run

Run the badge query grant (create)

client.grants.badgeQuery.runAll()

Custom Role

Operation

Request

What it does

Shortcuts

CustomRole_list

GET /orgs/{orgId}/custom-roles

List custom roles in an organization

forumulate roles list<br>client.roles.custom.list()

CustomRole_create

POST /orgs/{orgId}/custom-roles

Create a custom role in an organization

forumulate roles create<br>client.roles.custom.create()

CustomRole_update

PATCH /orgs/{orgId}/custom-roles/{id}

Update the custom role

forumulate roles update<br>client.roles.custom.update()

CustomRole_remove

DELETE /orgs/{orgId}/custom-roles/{id}

Delete the custom role

forumulate roles delete<br>client.roles.custom.remove()

Group Grant

Operation

Request

What it does

Shortcuts

GroupGrant_list

GET /orgs/{orgId}/group-grants

List group grants in an organization

client.grants.list()

GroupGrant_grant

POST /orgs/{orgId}/group-grants

Create a group grant in an organization

client.grants.grant()

GroupGrant_revoke

DELETE /orgs/{orgId}/group-grants/{id}

Delete the group grant

client.grants.revoke()

Group Identity

Operation

Request

What it does

Shortcuts

GroupIdentity_options

GET /orgs/{orgId}/group-identity

Get the group identity in an organization

client.groups.identity.options()

GroupIdentity_set

PUT /orgs/{orgId}/group-identity

Replace the group identity in an organization

client.groups.identity.set()

Invite

Operation

Request

What it does

Shortcuts

Invite_pending

GET /invites/pending

List pending invites

forumulate invites pending<br>client.invites.pending()

Invite_acceptPending

POST /invites/pending/{inviteId}/accept

Accept the pending

forumulate invites accept<br>client.invites.acceptPending()

Invite_accept

POST /invites/accept

Accept the invite

forumulate invites redeem<br>client.invites.accept()

Invite_acceptLink

POST /invites/accept-link

Accept link

forumulate invites join<br>client.invites.acceptLink()

Operation

Request

What it does

Shortcuts

LtiDeepLink_answer

POST /orgs/{orgId}/lti/deep-link

Create the deep link in an organization

client.ltiDeepLink.answer()

Member Merge

Operation

Request

What it does

Shortcuts

MemberMerge_preview

GET /orgs/{orgId}/members/{userId}/merge-preview

Preview merging a member into another

client.members.merge.preview()

MemberMerge_merge

POST /orgs/{orgId}/members/{userId}/merge

Merge a member into another

client.members.merge.merge()

Member Segments

Operation

Request

What it does

Shortcuts

MemberSegments_list

GET /orgs/{orgId}/segments

List segments in an organization

client.members.segments.list()

MemberSegments_create

POST /orgs/{orgId}/segments

Create a segment in an organization

client.members.segments.create()

MemberSegments_preview

POST /orgs/{orgId}/segments/preview

Preview who an unsaved segment matches

client.members.segments.preview()

MemberSegments_get

GET /orgs/{orgId}/segments/{segmentId}

Get the segment

client.members.segments.get()

MemberSegments_update

PATCH /orgs/{orgId}/segments/{segmentId}

Update the segment

client.members.segments.update()

MemberSegments_remove

DELETE /orgs/{orgId}/segments/{segmentId}

Delete the segment

client.members.segments.remove()

MemberSegments_previewSaved

GET /orgs/{orgId}/segments/{segmentId}/preview

Preview who a saved segment matches

client.members.segments.previewSaved()

MemberSegments_exportCsv

GET /orgs/{orgId}/segments/{segmentId}/members.csv

File of members (segments)

client.members.segments.exportCsv()

Public Identity

Operation

Request

What it does

Shortcuts

PublicIdentity_unlock

POST /public/orgs/{orgId}/spaces/{spaceId}/unlock

Unlock the space

client.public.identity.unlock()

PublicIdentity_unlockJwt

POST /public/orgs/{orgId}/spaces/{spaceId}/unlock-jwt

Unlock JWT in a space

client.public.identity.unlockJwt()

PublicIdentity_signupFields

GET /public/orgs/{orgId}/spaces/{spaceId}/signup-fields

List signup fields in a space

client.public.identity.signupFields()

PublicIdentity_register

POST /public/orgs/{orgId}/spaces/{spaceId}/register

Create the register in a space (public reader)

client.public.identity.register()

PublicIdentity_signIn

POST /public/orgs/{orgId}/spaces/{spaceId}/sign-in

Sign a reader in to a space

client.public.identity.signIn()

Rbac

Operation

Request

What it does

Shortcuts

Rbac_matrix

GET /capabilities

List capabilities

client.roles.capabilities.matrix()

Roles

Operation

Request

What it does

Shortcuts

Roles_list

GET /roles

List roles

client.roles.list()

Scim Admin

Operation

Request

What it does

Shortcuts

ScimAdmin_status

GET /orgs/{orgId}/scim/token

Get the token in an organization

client.sso.scim.status()

ScimAdmin_create

POST /orgs/{orgId}/scim/token

Create the token in an organization

client.sso.scim.create()

ScimAdmin_revoke

DELETE /orgs/{orgId}/scim/token

Delete the token in an organization

client.sso.scim.revoke()

Sessions

Operation

Request

What it does

Shortcuts

Sessions_list

GET /auth/sessions

List sessions

client.auth.sessions.list()

Sessions_revoke

DELETE /auth/sessions/{id}

Delete the session (auth)

client.auth.sessions.revoke()

Sessions_revokeOthers

POST /auth/sessions/revoke-others

Create a revoke other

client.auth.sessions.revokeOthers()

Space my access

Operation

Request

What it does

Shortcuts

Space_myAccess

GET /orgs/{orgId}/spaces/{spaceId}/my-access

Your access to a space

forumulate spaces access<br>client.spaces.myAccess()

The Forumulate teamUpdated