ak_…) under Settings → API for the Users API, or a personal key (pak_…) under My Account → Personal API Keys for the Accounts API.
- Two APIs, two key types, one plugin. The Users API manages your users, groups and events; the Accounts API manages team resources inside a Userflow account. An environment key cannot call
/accounts: Userflow answers401with the codeinvalid_pak. Both codes are treated as auth errors, so a missing or wrong key surfaces the same way — but only a personal key reaches members and invites. - The API version is pinned. Userflow has released one dated version and defaults every request to the latest, so this plugin sends
Userflow-Version: 2020-01-03explicitly, as the docs recommend. A later version cannot silently change the shapes underneath. - Creating and updating are the same call.
users.upsertandgroups.upserttake your own id: an unseen id creates the object, a known one merges only the attributes sent. Because of that, a400on a retried write is not the only risk — which is why a 5xx is replayed for reads only. - Groups or memberships, never both.
users.upserttakesgroupsfor simple membership ormembershipswhen the membership itself holds attributes such as a role. Sending both is rejected before the request. prune_membershipsis a delete. It removes every membership not listed, so sending it with no list would clear them all; the schema refuses that combination.- Relationships are opt-in.
groupsandmembershipscome back asnullunless you passexpand, and nesting works to four levels (memberships.group). Every read takes anexpandargument for this. - Paging is
has_more, not the link. Every list answersnext_page_url, and it is set even on the last page, so the plugin reportshas_moreand passesstarting_afterthrough rather than following the link blindly. - Sessions are the record of what was seen. A flow or checklist run is a content session;
contentSessions.listfiltered byuser_idandcontent_idanswers whether that person has seen it, andprogressis a decimal string from0to1. - Definitions are created by Userflow. Attribute and event definitions appear the first time an unseen name arrives, and the API can only list them — which makes
attributes.listthe way to discover what a workspace already tracks. - Webhook subscriptions are managed here; delivery is not. Each subscription has its own
whsec_…secret, returned only when the subscription is created (save it from that response), and notifications are signed asUserflow-Signature: t=<timestamp>,v1=<hmac>. The plugin manages subscriptions, but does not receive them, since there is no single workspace-wide signing key to verify against. - EU environments use a different host. An EU environment lives on
api.eu.userflow.com, and the key gives no hint of its region, so passregion: 'eu'to the plugin.
- 35 typed API operations
Setup
1
Install
2
Add the plugin
corsair.ts
multiTenancy: true, scope calls with corsair.withTenant(id). See Quick start for KEK + Hub keys, and Multi-tenancy for account isolation.3
Choose authentication
- API Key (Recommended)
No setup required yet. When you make your first request as a tenant, Corsair prompts for the API key.More: API Key
4
Connect a tenant
Mint a connect link and send the tenant to it. Hub hosts the page and delivers the result to your app — see Connect / OAuth.
Example API calls
List users ordered by signupWhat’s next
API reference
Every
userflow.api.* operation with input and output types.Connect / OAuth
createLink, Hub delivery, and tenant connect flows.
Use with agents
Expose this plugin’s operations as MCP tools.