Authentication & API keys
Mint API keys, understand scopes, rate-limit tiers, and enable write access.
Requests to the JOGL Network API are authenticated one of two ways: a personal API key (for REST, and for MCP clients that are not connected over OAuth), or a short-lived OAuth access token issued through the WorkOS AuthKit connector (the one-click MCP connector path, see MCP server). Keys are minted by you, for you, and inherit your rights at the time each call is made.
Minting a key
Go to Settings → API/MCP in the app and create a key. A key belongs to your personal billing owner and carries exactly your own rights, which are not the same for reading and writing:
- Reading — every non-archived community you belong to, in any role, plus any
non-archived community owned by an organization you manage. Ordinary membership is enough;
you do not have to be an admin. Archiving a community takes it out of the key's reach even
though your membership row survives, so a read against it returns
403andscope: "all"simply omits it. - Writing — only where you are an admin or owner of the community, directly or through an organization that owns it. See Enabling write access below.
A new key always reaches that whole set: attaching a community allowlist to narrow it is no
longer supported, and a create request that carries one is rejected with 400. A key created
earlier with an allowlist keeps it, and it still narrows that key (never expands it).
Keys are always personal. Organization-owned keys can no longer be created; a legacy org-owned key that already exists keeps working until you revoke it, but it never inherits its minter's personal community-admin rights (it acts on ownership only).
The full secret is shown once, at creation, and is never recoverable afterwards. Store
it somewhere safe. Only a hash and a display prefix (e.g. jogl_live_AbCd1234) are kept.
Revoke a leaked key in Settings; revocation takes effect on the next request.
Keys are prefixed jogl_live_ (live) or jogl_test_ (test). The prefix is a label, not a
boundary — a jogl_test_ key reads and writes the same data as a live one on the deployment
that minted it. See the warning on the API keys page.
Presenting a key
Send the key on every request as either header:
Authorization: Bearer jogl_live_…X-API-Key: jogl_live_…Scopes
Scopes are chosen at mint time. Most come in two tiers; self:enrich, contact:write,
notes:read, notes:write and settings:write, described after the tables, are in neither.
Read tier — mintable by any signed-in user, no attestation:
| Scope | Grants |
|---|---|
search:read | Expert search |
profile:read | Read your own profile, the people you know, and a community's roster, members, event attendee lists and analytics |
enrich:read | Poll enrichment run status |
history:read | Read your own past searches, including searches made in the app |
Write tier — needs the community billing owner's Write access on, which it is by default (see below):
| Scope | Grants |
|---|---|
member:write | Add people to a community you control, and community-scoped erasure |
enrich:write | Start enrichment on members of a community you control |
community:write | Create a community you own and pay for |
crm:write | Map and run the syncs of the CRMs connected to a community you control (creating the community fields a mapping needs and choosing who sees them), and make a link to connect one (never a CRM key) |
self:enrich (enrich your own profile, target-locked) is also mintable by any signed-in
user with no attestation, but because it starts a billable side effect it is not part
of the one-click Read preset in the create-key UI — select it explicitly under
Advanced. A plain "Read" key can't call POST /v1/me/enrich.
contact:write (send members direct messages in JOGL as you, and ask attendees of events you
attend for meetings, each one previewed before it is sent; see
Direct messages and
Meeting requests) is the same: mintable by any
signed-in user with no attestation, in neither preset, selected under Advanced. It needs a
key of your own; a legacy organization-owned key cannot send, since a message or a request goes
out under a person's name. Of the write checks below, it needs only your own account's Write
access (check 2, read for your account rather than a community's owner): while it is off,
every send, preview and slot listing returns 422 unprocessable. The community checks do not
apply, since a send changes no community's data: whether a member can be messaged follows their
own message settings, and whether an attendee can be asked for a meeting follows the event, as
in the app (a block between you and them,
made by either of you, refuses both), so turning a community's API writes off does not stop it.
community:write creates a community owned by you and billed to you, as the app's New
community page does (see Creating a community).
It needs a key of your own with no community allowlist, and of the write checks below only your
own account's Write access (check 2, read for your account), since the community does not
exist yet: while it is off, the call returns 422 unprocessable. Your free trial or plan must
cover the new community. The API cannot start a trial, so without one the call returns
402 coverage_required with a link to the app.
crm:write maps and runs the syncs of the CRMs (Airtable, HelloAsso, Odoo) a community admin
connected in the app, on the key that connection saved (see
CRM syncs). It takes the same write checks as adding
members. No route or tool takes or returns a CRM key: connecting a CRM, or reconnecting one
whose key no longer works, is done by an admin of the community who types the key on a JOGL page,
in the app or on the page a connect link opens.
notes:read and notes:write (read the private notes you keep on people's profile pages in the
app, and add one as you; see Private notes) are the
same again: mintable by any signed-in user with no attestation, in neither preset, selected under
Advanced, and only on a key of your own. They reach only the people you can see in JOGL, and
a note in which AI structuring marked a detail as sensitive comes back withheld. A note never run
through AI structuring comes back as you wrote it, so tick notes:read only for an agent you would
show your notes to. Adding a note needs only your own account's Write access, as
contact:write does.
settings:write (change some of your own settings as you: who can see your profile, who can
message you or send you connection requests, the notification and admin-reminder emails JOGL
sends you, and turning on the use of your notes as context; see
Account settings) is the same again: mintable by any
signed-in user with no attestation, in neither preset, selected under Advanced, and only on a
key of your own. It changes nobody else's settings, and none of those that stay in the app (write
access itself, data residency, billing, keys, deleting your account). A profile can be made public
only once JOGL has verified your account. Like adding a note, a change needs only your own
account's Write access. Reading those settings needs profile:read, and the notes switch
notes:read. Turning your notes as context off needs only notes:write; turning it on
needs settings:write as well.
Enabling write access (attestation)
Carrying member:write or enrich:write is not enough. Those writes are gated at use time by
three checks:
- Ownership or community-admin — your billing owner must be the target community's billing
owner, or — for a personal (user-owned) key only — your owner must be an admin of
the community. A legacy organization-owned key never gets that second path (see above): it
acts on ownership alone, so it still gets
403for a community its organization does not own, even when the person who minted it administers that community. The delegated-admin path applies to all three community writes — adding members (member:write), starting enrichment (enrich:write), and member erasure — unless the community's billing owner has turned off check 2 or check 3. - Write access — the community's billing owner's Write access must be on. It is on by default, and an owner can turn it off; turning it back on records a versioned, auditable attestation.
- The community's admin switch, when you reach the community as an admin rather than as
its owner. Its switch, Admins can write through the API, is on by default for every community; its
owner can turn it off in the API & AI tools section of the community's admin dashboard or under Settings →
API/MCP → Write access → Community admins. While it is off, an admin's write call returns
422 unprocessable; the owner's own calls do not need it.
The owners and admins of the organization that pays for a community act as its owner while
they hold one of the organization's seats, so they need only check 2. Write access is in Settings → API/MCP → Write access. While it is off,
write calls return 422 unprocessable. When the just-in-time consent feature is switched on for your account,
a call refused by check 2 returns 422 owner_consent_required instead and queues a consent
request the owner can approve under API write requests in Settings → API/MCP; retrying
the same call after approval then succeeds. A call refused by check 3 is not queued: approval would not
change the community's admin switch.
Rate limits
Each key has a per-minute token bucket. For an API key, the tier is decided when the key is minted and stored on the key, so upgrading your plan later does not change an existing key — mint a new one. An OAuth connector follows your account instead: its tier is read again at every call, so it moves to the standard tier on the next call once you are privileged, and back to the restricted tier if you stop being privileged (calls you already made that UTC day still count, so past the 20th you wait until midnight UTC). You never need to reconnect for it.
- Restricted (free) tier — 2 requests/min, burst 5, and a hard 20/day cap (the day is UTC). This is the default for an owner who is not privileged.
- Standard tier — the requested rate (default 60/min), full burst, and no daily cap. You are privileged when any of these holds (for an API key, at mint time): your billing owner is an organization; your owner has an active paid plan (a free trial does not count); you are the owner or admin of at least one community; or you are an owner or admin of an organization that owns at least one community, which carries the same tier your retired org-owned key used to get. An OAuth connector is also on the standard tier, at 60/min, when you are a member of a community whose owner has bought a plan (a free trial or a complimentary plan does not count, nor does an archived community or one that anyone can join without approval). An API key is not tiered that way.
Every REST request counts against the limit. Over MCP only a tool call counts: connecting,
listing tools and other protocol messages are free, so a new chat does not spend part of the day's
calls before the first tool runs. GET /v1/me and the MCP get_me tool return your limits and
today's count under limits.
Don't hardcode a rate — read the RateLimit-Limit, RateLimit-Remaining, and
RateLimit-Reset headers on every authenticated response and pace off RateLimit-Remaining.
Exceeding the limit returns 429 with a Retry-After header.
OAuth (one-click connectors)
Instead of a static key, an MCP client can connect via OAuth (WorkOS AuthKit). The bearer
token is then a short-lived JWT rather than a jogl_* key. Authorization is always re-checked
against live key state, so revoking a grant takes effect immediately. See
MCP server.
A connector approved on its consent screen gets the read scopes and the write tier
(member:write, enrich:write, community:write, which every connector that already held the
write tier also received when it was added, and crm:write, which a connector made before it was
added gains only from its card, below): the screen lists them and the write attestation, and
approving it accepts that attestation for your personal account, which turns API write access
on for that account. Its read scopes include history:read only when it was approved after that
scope was switched on for connections (see MCP server), and a
connector never carries self:enrich: self-enrichment needs a static key. A connector approved on
a consent screen that also lists sending members messages and meeting requests, as every screen
has since that permission was added, carries contact:write beside the write tier; one approved
on an earlier screen does not, and a reconnect may keep the original approval. Its card under
Settings → API/MCP → Connected apps then offers Add new permissions, which adds
contact:write, while write is on for the connector, once you approve; revoking it there and
connecting the client again also works. The same card offers crm:write, while write is on, to a
connector made before that scope was added. The private notes work the same way: a connector approved
on a screen that lists reading and adding your private notes carries notes:read, and
notes:write beside the write tier; one approved on an earlier screen carries neither until you
add them from its card, or revoke it and connect again. A connector approved on a screen that
lists changing your own settings carries settings:write beside the write tier; one approved on an
earlier screen gains it from its card, while write is on for it. Its writes are still gated at
use time by the three checks above. To make a connector read-only, turn write off on it under
Settings → API/MCP → Connected apps once it has connected; that takes contact:write,
notes:write and settings:write off too, and keeps notes:read. Turning write back on gives
back each of those three the connector held when you turned it off, including one you added from
its card. A connector approved before, or
in the hour after, full access became the default stays read-only until you turn write on there.
The assistant can tell you when its connection can be given more: get_me lists those
permissions under connection.new_permissions with a link, connection.add_permissions_url, that
opens the connector's Add new permissions dialog in JOGL, where you approve them with one
click. The assistant cannot add them itself.