Teams started as a dashboard feature. The CLI, SDK, and MCP server could read an endpoint a teammate shared with you, and that was all. They could not search its requests, share an endpoint of your own, or show how much of the team's pool was left. For anything else you opened a browser.
CLI 1.3.0, SDK 1.10.0, and MCP server 1.8.0 close that gap. Sharing, membership, invites, search, and pooled quota now work from the terminal, from code, and from your AI agent.
What shipped
- CLI 1.3.0: a
whk teamscommand group,whk list --team, and team pools inwhk usage. - SDK 1.10.0: a
client.teamsnamespace andendpoints.list({ team }). - MCP server 1.8.0: four new tools (
list_teams,list_team_members,share_endpoint,unshare_endpoint), bringing the total to 35. - API: request search and count now cover endpoints shared with you, not only endpoints you own.
No new credentials are involved. An API key carries exactly the team access of the account it belongs to, so the key from your account page, or a whk auth login session, already works.
A shared endpoint behaves like your own
Any endpoint shared with you through a subscribed team can be listed, inspected, streamed, searched, and forwarded by slug. The most useful consequence: you can tunnel a teammate's endpoint to your own machine.
whk list --team Payments # endpoints tied to one team
whk listen <shared-slug> # stream a teammate's endpoint
whk tunnel 3000 --endpoint <shared-slug> # forward it to your localhostSay one person owns the staging Stripe endpoint. A teammate who needs to debug the invoice.paid handler runs whk tunnel against that slug and receives the same events on localhost:3000. Nobody registers a second webhook URL with Stripe, and nobody pastes payloads into chat.
--team takes a team name or id. It matches in both directions: endpoints shared with you from that team, and your own endpoints that you shared with it. In the SDK and the API, each endpoint says which case applies. sharedWith marks an endpoint of yours that a team can see. fromTeams lists every one of your teams that a teammate's endpoint is shared with.
Search covers the whole team
Before this release, search only looked at endpoints you owned. A teammate's endpoint appeared in your list, but its requests never appeared in your search results. Now they do:
whk requests search --q invoiceEach hit shows its endpoint slug, so you can tell whose endpoint caught the request. The SDK methods client.requests.search() and client.requests.count() pick up the same change with no code changes on your side.
Retention follows the endpoint, not the person searching. Requests billed to a team are kept for 31 days, so a teammate on the Free plan can search a month of shared traffic.
Share and invite without the browser
whk teams mirrors the team page:
whk teams list # role, seats, members, pooled usage, status
whk teams members Payments # members and pending invites
whk teams share my-stripe --team Payments # endpoint owner only; needs an active team
whk teams unshare my-stripe --team Payments
whk teams invite Payments [email protected] # team owner only; sends an email
whk teams invites # invites waiting for you
whk teams accept <invite-id>
whk teams decline <invite-id>Wherever a command takes a team, pass its name (case-insensitive) or its id. If a name matches more than one team, the command fails and asks for the id instead of guessing. Every subcommand supports --json for scripts.
Sharing has a billing effect: from the moment you share an endpoint with an active team, its requests draw from the team's pooled quota rather than your personal plan.
Invites also changed since the last Teams post. You can invite any email address, whether or not it has a webhooks.cc account. The invitee gets an email, signs up with that address (email and password, GitHub, or Google), and finds the invite waiting. If the invite was created but the email could not be sent, the CLI tells you so.
The same operations in code
The SDK exposes everything under client.teams. One use: have CI share the endpoint it creates, so that anyone on the team can inspect a failing run.
import { WebhooksCC } from "@webhooks-cc/sdk";
const client = new WebhooksCC({ apiKey: process.env.WHK_API_KEY! });
const endpoint = await client.endpoints.create({ name: "ci-stripe-checkout" });
const teams = await client.teams.list();
const payments = teams.find((team) => team.name === "Payments");
if (payments && !payments.suspended) {
// Takes the slug and resolves the endpoint id for you
await client.teams.share(payments.id, endpoint.slug);
}When the test fails at 2 a.m., whoever picks it up in the morning opens the endpoint in their own dashboard and sees the requests the test received. The API key must belong to the endpoint's owner, because only the owner can share.
The rest of the namespace follows the CLI:
const { members, pendingInvites } = await client.teams.members(payments.id);
await client.teams.invite(payments.id, "[email protected]");
const invites = await client.teams.invites.list();
await client.teams.invites.accept(invites[0].id);
// Filter endpoints by team id or name
const shared = await client.endpoints.list({ team: "Payments" });An unknown team name throws. So does a name that matches more than one team.
See the pool before you run out
A team's requests come from one pool: 100,000 per seat per 30 days. When the pool is empty, the receiver answers 429 Too Many Requests until the period resets. Until now, the team page was the only place to see how close you were.
whk usage now prints each subscribed team's pool under your personal plan, and whk usage --json adds a teams array. In the SDK, teams.list() returns requestsUsed, requestLimit, seats, and periodEnd for every team, which is enough to guard a load test:
const team = (await client.teams.list()).find((t) => t.name === "Payments");
if (!team) throw new Error("Not a member of Payments");
const remaining = team.requestLimit - team.requestsUsed;
if (remaining < 20_000) {
throw new Error(`Payments pool has ${remaining} requests left; skipping load test`);
}What your agent can do, and what it can't
The MCP server gains four tools: list_teams, list_team_members, share_endpoint, and unshare_endpoint. list_endpoints accepts a team filter, and get_usage reports each team's pool next to your personal plan. Prompts like these now work in Claude Code, Cursor, or Codex:
- "Share my-stripe with the Payments team."
- "Which endpoints has the Payments team shared with me? Show the latest request on each."
- "How much of the Payments pool is left this period?"
Invites are deliberately missing. Accepting an invite claims a paid seat, and sending one emails a real person. Both are decisions for a human, so they stay in the CLI, the SDK, and the dashboard, where a person runs them on purpose.
Keys that an agent registered for itself follow the same logic: an unclaimed agent key has no team access until a human claims it.
Creating, renaming, and deleting teams, removing members, and everything about billing remain dashboard actions. Billing routes reject API keys outright.
Permissions are unchanged
The clients enforce the same rules as the dashboard:
- Only the endpoint owner can share or unshare an endpoint.
- Only the team owner can invite.
- Members can view requests and edit an endpoint's settings and mock response.
- Members cannot delete a shared endpoint or clear its requests.
requests.clearin the SDK and the MCPclear_requeststool stay with the owner. - A suspended team (one with no active subscription) shares nothing until it resubscribes.
Upgrade
whk update
whk --version # 1.3.0 or laterFAQ
Teams Documentation
Sharing, permissions, pooled quota, and the full CLI, SDK, and MCP reference for teams.
CLI Command Reference
Every whk command, including the new teams group.