/management/*) to manage organizations, members, and quotas. Every example is
plain Python 3 with requests.
The tutorials cover the following operator flows:
- Create an organization
- Add users to an organization
- Remove users from an organization
- Set quotas for an organization
- Set up a billing hierarchy (parent and child orgs)
Prerequisites
- A Snowglobe account with
billing_adminaccess. Sign up here. - A Snowglobe API key (see Setup below).
- Python 3 with
requestsinstalled (pip install requests).
Setup: shared client
Every request is authenticated with an API key sent in thex-api-key header.
Generate a key from the Snowglobe web app (under your account/organization
settings) and export it as an environment variable. All examples below reuse this
one client.
Roles
Most flows are role-gated. The four roles areowner, admin, billing_admin,
and member.
A
403 almost always means your API key’s roles don’t satisfy the row above,
not that the org is missing (that returns 404).
Quick start: onboard a customer end-to-end
This routine chains the common onboarding path into one function: create the org, invite the initial admins and members, set the quota, and verify the result. It calls helpers defined in the flows below (create_organization_full in
Flow 1, create_invitations in
Flow 2, and set_quota /
get_organization in Flow 4), so copy
those in alongside the shared client. Each flow below
explains one piece in depth.
- The caller is assigned
billing_adminon the new org automatically, and is the only account added directly. Everyone else, whether passed inmembersat create-time or through the invitations endpoint, and regardless of role, must accept an invitation before they join. So the admins and members here all show up underpending_invitationsuntil they accept. - The caller must be a
billing_adminfor step 1 (create) and step 3 (quota). The same API key is fine for the invitations in step 2, sincebilling_adminsatisfies that gate too. - To onboard a customer under a billing parent, pass
billing_org=parent_id(see Flow 5).
Flow 1: Create an organization
Endpoint:POST /management/organizations
Who: the authenticated user must be a billing_admin.
Minimal create
Onlydisplay_name is required.
201 response is the full Organization object. The fields you’ll most
often key off of afterwards:
Create with members, a billing parent, and an initial quota
You can seed people in the same call that creates the org.members here is a
list of OrganizationMemberInput, the same shape used to invite people in
Flow 2 (each needs roles, plus id or email).
The caller (the billing_admin making this request) is the only account added
to the org directly. Everyone listed in members receives an invitation and
must accept it before they appear in org["members"], regardless of the role
they’re assigned. In other words, passing someone in members is a shortcut for
inviting them at create-time, not a way to add them without acceptance.
billingOrg rules:
- The referenced org must already exist.
- It must not itself have a
billingOrg. Nested billing hierarchies are rejected. A parent can have many children; a child cannot be a parent. - Violating either rule returns
400.
Confirm it exists
GET on an org you have no role in returns 403; a missing id returns 404.
Flow 2: Add users to an organization
Endpoint:POST /management/organizations/{orgId}/invitations
Who: the caller needs owner, admin, or billing_admin in that org.
How adding a user works
There is no add-member-directly endpoint. You invite users, and they becomemembers once they accept. The lifecycle:
Batch-invite
The request body is an array ofOrganizationMemberInput. Each entry needs
roles and at least one of email or id. When only id is given, the server resolves the email via
the auth provider at send-time.
OrganizationInvitation objects, including the
invitation_url each invitee must follow to accept.
Common 400 causes: an entry missing roles, or an entry with neither id nor
email.
List invitations to track who hasn’t accepted
This endpoint returns only unaccepted invitations, so everything it returns is still pending; no client-side filtering is needed. An invitation drops out of the list once the invitee accepts.Verify the user landed as a member
After the invitee accepts, they move frompendingInvitations into members:
Flow 3: Remove users from an organization
Membership changes run through the invitation lifecycle, so the operator task here is to audit who currently has access, both active members and outstanding invitations, and confirm the resulting state.Flow 4: Set quotas for an organization
Endpoints:PUT /management/organizations/{orgId}/quota (set/replace),
DELETE /management/organizations/{orgId}/quota (clear).
Who: the caller must be the billing_admin of that specific org.
What a quota is
A quota is a singleDimensionedValue:
amount: an integer cap that applies per billing period. Billing periods are monthly in practice, so the quota is effectively a monthly cap;usageresets each period.unit: a string. In practice it is always"conversations", and the server defaults it to"conversations"when omitted, so you don’t have to send it. Sending it explicitly makes the code more readable, and the field is left open for forward compatibility.
PUT overwrites the previous value
wholesale. There is no separate “add 10k” call at this layer.
The kinds of quota-related values
The API models three distinct numeric concepts. Only the first is settable here; the other two are read-only. Keep them separate so you don’t confuse them with the quota.
When someone says “set the quota,” they mean the first row: a
conversations cap
via PUT. Usage and adjustments are surfaced for visibility (see
reading them back below) but are not
writable through this API.
Set or replace a quota
200 response echoes back the stored DimensionedValue. Raising or lowering
the cap later is the same call with a new amount.
Remove a quota (back to unlimited/unconfigured)
DELETE returns 204 No Content, so there is no body to parse.
Read quota, usage, and billing back
Quota and usage ride directly on theOrganization object. Historical billing
(usage, adjustments, and final billed amount per period) comes from the
billing-reports endpoint.
billing_admin, the billing-reports endpoint also returns
reports for any child orgs billed under this one (those whose billingOrg points
here). A non-billing-admin sees only the org’s own reports.
Flow 5: Set up a billing hierarchy (parent and child orgs)
Snowglobe supports a one-level billing hierarchy: a parent org that carries the billing relationship, and any number of child orgs billed under it. This is the reseller / multi-tenant pattern. Each customer team gets its own org, with its own members and quota, but the bills roll up to a single parent.The nesting rule
billingOrg may point only at an org that does not itself have a billingOrg:
400.
Build the hierarchy
create_organization_full is defined in Flow 1.
Guard against the nesting error
If you’re building the hierarchy from data you don’t fully control, check the prospective parent before you point at it. An org that already has abillingOrg
cannot serve as a parent:
Read the whole hierarchy’s billing at once
When the caller is abilling_admin, the parent’s billing-reports endpoint
returns reports for the parent and every child billed under it, so a single call
gives you the consolidated view:
billing_reports is defined in Flow 4.
Setting or clearing a quota is always per-org (there is no inherited quota), so
use Flow 4 against each child id to
adjust its cap.
Appendix: status codes
The
request() helper at the top raises RuntimeError with the server’s body on
any 4xx/5xx code, so failures surface the actual reason rather than a bare status
number.