Organization
Manage the workspaces inside your organization from one API key, allocate sender seats, and act on any of them with a single request header.
An organization workspace on Swarmhit holds the billing and the sender-seat pool, and contains any number of ordinary workspaces underneath it. The API mirrors that: one organization key manages every workspace inside it, without a separate key per workspace.
The model
| Organization | Workspace inside it | |
|---|---|---|
| Billing and plan | Owns them (isOrganization: true) | Inherits from the parent organization (isSubWorkspace: true) |
| Sender seats | Holds the pool; seatLimit is the pool minus seats handed out | seatLimit is its seatAllocation from the pool |
| Members | Organization owners/admins | Its own members, plus read-only organization managers granted via the organization |
The getApiInfo endpoint (GET /) returns the connected workspace with isOrganization, isSubWorkspace, the effective plan, seatLimit and seatsUsed, which makes it a quick way to check what a key (or a header, see below) resolves to.
Managing workspaces
The Organization endpoints live under /workspaces and require the key's workspace to be an organization (anything else gets 403, and listWorkspaces returns isOrganization: false with an empty workspaces list).
List workspaces
Every workspace plus the seat pool: pool, allocated, available.
Create a workspace
Name it and optionally grant seats from the pool.
Update a workspace
Rename, set the avatar, or change the seat allocation.
Delete a workspace
Allowed only once its sender accounts are disconnected.
Create a workspace and grant it two sender seats from the pool:
curl -X POST https://app.swarmhit.com/api/v1/workspaces \
-H "Authorization: Bearer swh_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"name": "Acme Inc.", "seatAllocation": 2}'Seat math is enforced on write: updateWorkspace rejects with 400 if you lower a workspace's allocation below its connected senders, or allocate more than the organization pool has available. deleteWorkspace rejects with 400 while the workspace still has connected sender accounts: disconnect them first (see Sender accounts).
Workspace members
Each workspace has three membership groups, returned by listWorkspaceMembers and on getWorkspace:
members: the workspace's own staff, with rolesowner,adminormember.orgMembers: organization owners/admins granted access via the organization. Read-only here; they cannot be changed or removed through the members endpoints.invites: pending email invites (adminormember; the invite token is never returned).
Invite someone into a workspace with inviteWorkspaceMember (role defaults to member):
curl -X POST https://app.swarmhit.com/api/v1/workspaces/aBc123/members \
-H "Authorization: Bearer swh_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"email": "jane@acme.com", "role": "member"}'updateWorkspaceMember and removeWorkspaceMember work on both members and pending invites: pass type: "user" (default, memberId is the user id) or type: "invite" (memberId is the invite email; on delete, use the ?type=invite query parameter). The workspace's ownerId (the org admin who created it) cannot have their role changed or be removed.
Acting on a workspace: the X-Swarmhit-Workspace header
An organization key can operate on any workspace inside it by naming the target in a request header:
X-Swarmhit-Workspace: <workspaceId>With the header set, every data endpoint (campaigns, leads, accounts, inbox, and so on) acts on that workspace. Omit it to act on the organization itself. Same endpoint, same key, two workspaces:
# Campaigns of the organization workspace
curl https://app.swarmhit.com/api/v1/campaigns \
-H "Authorization: Bearer swh_live_xxxxxxxxxxxxxxxxxxxxxxxx"
# Campaigns of workspace aBc123, same key
curl https://app.swarmhit.com/api/v1/campaigns \
-H "Authorization: Bearer swh_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Swarmhit-Workspace: aBc123"The rules are strict, and worth internalizing:
- The header is only honored for an organization key targeting one of its own workspaces. Any other value (a foreign workspace id, a typo, a non-organization key) is rejected with
401. It never silently falls back to the key's own workspace, so a bad id cannot accidentally read or write the organization's data. - The
/workspacesendpoints always manage the key's organization, regardless of the header. You cannot nest: a workspace inside an organization cannot contain workspaces of its own.
To confirm what a header resolves to before doing real work, call GET / with the header set. The returned workspace will show the target's id with isSubWorkspace: true.
Everything workspace-scoped follows the header. For example, connectSender with the header set connects the LinkedIn account into that workspace and consumes a seat from its allocation. See Authentication for how keys are created and scoped in the first place.
Webhooks per workspace
Webhook endpoints belong to a workspace, and events deliver to the endpoints of the workspace where they occurred. A reply received in one workspace's inbox fires only that workspace's webhooks, never the organization's.
So to receive a workspace's events, register an endpoint on that workspace by calling createWebhook with the X-Swarmhit-Workspace header:
curl -X POST https://app.swarmhit.com/api/v1/webhooks \
-H "Authorization: Bearer swh_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Swarmhit-Workspace: aBc123" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/hooks/acme", "events": ["message.received", "connection.accepted"]}'You can point every workspace at the same receiver URL and tell them apart by the signing secret each endpoint gets at creation (or by a path or query parameter you bake into each URL). Payload verification and retry behavior are covered in the Webhooks guide.
MCP server per workspace
The MCP server does not use the header. The acting workspace is fixed per connection instead: append workspaceId to the connection URL.
https://app.swarmhit.com/mcp?key=swh_mcp_xxxxxxxxxxxxxxxxxxxxxxxx&workspaceId=aBc123The same rule applies as on REST: the key must belong to an organization and workspaceId must name one of its own workspaces, otherwise the connection is rejected. Configure one MCP connection per workspace you want an AI agent to operate.
The organization endpoints have MCP equivalents too: list_workspaces, get_workspace, create_workspace, update_workspace, delete_workspace, invite_workspace_member, update_workspace_member and remove_workspace_member, each taking a workspaceId argument. get_workspace_info is different: it returns the workspace the connection itself resolves to.
A typical onboarding flow
createWorkspacewith a name and aseatAllocationfrom the pool.inviteWorkspaceMemberto give that team access to their workspace.- With
X-Swarmhit-Workspaceset to the new workspace's id: connect senders, create webhooks, then build campaigns and import leads. - Periodically call
listWorkspacesto watchpool/allocated/availableand each workspace'ssendersUsedagainst itsseatAllocation.