Recipes

Team plans for business buyers

Sell a plan to a customer's team. The team is one buyer organization, its members are invited by email, and everything they use counts against the allowance the organization bought.

This recipe sells a Team plan with 1,000 report exports a month, shared by everyone on the customer's team. When you are done:

  • the person who buys becomes the owner of the customer's organization and invites colleagues by email;
  • a colleague who joins works in the same organization, so their exports count against the same 1,000;
  • only the owner and admins can change billing or invite; members just use the product.

There is nothing team-specific in your backend. A buyer organization is the unit that subscribes, and the session token of every member names it, so ruling and reporting by organization_id already shares the allowance.

How it works

ObjectIn this recipe
Buyer organizationThe customer's team, for example Acme Analytics. It holds the subscription and the allowance
MemberAn end-user account in that organization, with the role OWNER, ADMIN, MEMBER or VIEWER
Session tokenIssued to one end user, for one organization at a time; organization_id in its claims is that organization

Buyer organizations describes roles, invitations and switching in full.

1. Define the Team plan

Create a plan with the allowance shared by the team, as in the other recipes:

The rule of Team's first version
PUT /mgt/v1/projects/{projectId}/plans/{planId}/versions/1/rules
Authorization: Bearer <operator session token>
Content-Type: application/json

{ "rules": [{ "capability_id": "<report_exports>", "allowance": 1000, "reset_interval": "MONTHLY" }] }

Then publish it. The allowance belongs to the organization, not to each member: five members share 1,000, they do not get 1,000 each.

2. The buyer signs up and subscribes

The person who signs up without an invitation gets an organization of their own, with the name they give and them as owner. They subscribe it to Team through PricingTable and checkout; as an owner or admin, they are allowed to change billing. This needs Allow self sign-up turned on, under Settings, Project, Customer sign-in. It is off by default, and until it is on no end user can create an account, not even an invited one; see Who may create an account.

3. The owner invites the team

Owners and admins invite by email, with the Public API and their own session:

http
POST /public/v1/organizations/{orgId}/invitations
Authorization: Bearer <access token of an owner or admin>
Content-Type: application/json

{ "email": "<invited email address>", "role": "MEMBER" }

{orgId} must be the organization of the session. ShipRev mails the invitation; the token travels only in that email, with a link to the hosted invitation page on your brand domain, or to your own sign-in page with an invitation_token query parameter if you set a custom sign-in address.

Give owners and admins a place to do this in your product, for example a members page that calls this endpoint through your forwarding path.

4. The colleague joins

What the invited person does depends on whether they already have an account on your gate:

TheyWhat they doResult
Have no accountSign up from the invitation: POST /public/v1/auth/register with email, password and invitation_token, or the hosted pageTheir account joins the inviting organization and gets no organization of its own. The email is verified by the invitation, so the session is issued at once
Already have an accountSign in, then POST /public/v1/invitations/accept with { "token": "<invitation token>" }They become a member, and keep their other organizations

GET /public/v1/invitations/info?token=<token> shows the organization's name, the email and the role before either, without a session.

Someone who belongs to more than one organization works in one at a time. GET /public/v1/organizations lists them and POST /public/v1/auth/switch with an organization_id returns an access token for the other one. Your backend sees whichever organization the token names.

5. Your backend: nothing changes

Rule and report with the organization from the verified token, as on any route:

ts
const claims = await shiprev.verifyToken(token); // the member's own session
const ruling = await shiprev.adjudicateAsync({
  organization_id: claims.organization_id, // the team's organization
  capability_key: 'report_exports',
  quantity: 1,
  operation: 'write',
});
// ... run the export, then report it with the same claims.organization_id

What one member uses, every member sees used. If a member exports 40 times and the owner 10 times, both of them are ruled with remaining 950 and limit 1,000, and UsageMeter shows 50 used to either of them.

Your backend receives the organization in the token, not the member's role. Decide what a member may do in your product with the organization's entitlements, and keep finer permissions of your own, such as who may delete a report, in your application.

6. What members can and cannot do in ShipRev

ActionOwner, adminMember, viewer
Use the product within the allowanceYesYes
See the subscription, members and usageYesYes
Invite, change roles, remove membersYes; only owners manage other ownersRefused with 403 FORBIDDEN
Change plan, cancel, payYesRefused with 403 INSUFFICIENT_ROLE

Show billing and invitation actions only to owners and admins. The session that sign-in and sign-up return carries the role in account.current_role, for the organization the session is in; a refused request reaches the components' onError.

Try it

  1. Publish Team and sign up a test end user, the owner. Activate their organization on Team, through checkout in Stripe's test mode or by hand with POST /mgt/v1/projects/{projectId}/subscriptions/activate.
  2. Invite a second address as MEMBER, open the mail and sign up from it. Verify the new member's token in your backend: organization_id is the owner's organization.
  3. Export as the member, then as the owner. Both rulings show the same remaining.
  4. As the member, try POST /public/v1/subscriptions/cancel. Expect 403 with INSUFFICIENT_ROLE.
  5. Invite an address that already has an account of its own, accept as that account, switch to the team's organization and verify the new token: it names the team's organization.

Variations

  • More allowance for larger teams. Publish a second plan, Business, with a larger allowance; the owner moves the organization to it like any plan change.
  • Several teams per customer. Each team is its own organization with its own subscription; an end user can be a member of several and switch between them.

Where to go from here

© 2026 ShipRev