Skip to main content

Workspaces

The Scripe API is workspace-scoped end-to-end: every read returns data only the active workspace owns. /v1/workspaces/me resolves the active workspace plus the principal that’s calling; /v1/workspaces lists every workspace the caller can reach; /v1/workspaces/context folds the me block together with the review gate and an enriched project overview in one call; /v1/team lists the workspace’s members. API keys authorise exactly one workspace — to act on a different workspace, mint a key there. OAuth tokens can reach every workspace the consenting user belongs to: the workspace pinned at consent is the default, and a per-request Scripe-Workspace-Id header targets any other (see Multi-workspace access).

GET /v1/workspaces/me

Returns the authenticated workspace’s metadata, the principal making the request, and the feature flags currently enabled for the workspace’s plan.

Response

Field reference

The features object grows over time. Treat unknown keys as false when introspecting; a true for a flag we haven’t shipped yet means your client predates the dashboard’s option.

Caching

The response is not cacheable — it depends on the request’s principal and reflects live plan state. Don’t memoise it for longer than it takes to render the next page. If you need workspace metadata frequently (e.g. you’re showing the plan in your UI), cache the response in your own client for a minute and invalidate on plan-change webhooks.

Why not just decode the API key?

Two reasons:
  1. Plan changes propagate. The plan in the response reflects the workspace’s current Stripe state, not what was true when you minted the key. A workspace that downgrades will see apiAccess: false here before any other endpoint starts 403’ing.
  2. One endpoint, both credential kinds. An OAuth token gets principal.type: "oauth_token" from the same endpoint, carrying clientId, actingUserId and defaultProject so you know which client is acting and on whose behalf. Decoding a key tells you none of that.

Errors

workspace.name resolves through the same tolerant lookup as GET /v1/workspaces: an unresolvable Clerk org degrades the name to "" rather than failing the call, so this endpoint no longer returns 503 service_unavailable. See errors/ for full descriptions.

GET /v1/workspaces/context

The one-call overview: everything /v1/workspaces/me returns, plus the workspace’s review gate and its projects enriched with LinkedIn connection health and posting streaks. Requires the workspace:read scope — which today means an OAuth token, since the API-key catalogue doesn’t offer that scope yet (see auth.md §1.2). The field-by-field schema is WorkspaceContext in the OpenAPI reference tab.
workspace and principal are byte-identical to /v1/workspaces/me; each entry of projects is a /v1/projects row — including its linkedIn block — plus a posting streak:
Two things to hold on to:
  • linkedIn is stored health, not a live check. It is what Scripe last recorded, valid as of lastValidatedAt — this endpoint never probes LinkedIn. The live check runs where it matters: the schedule / publish pre-flight. It is the same block GET /v1/projects serves; read canPublish / state rather than connectionStatus, which says CONNECTED for accounts that hold no token (field reference). streak is null for company pages and for projects with none yet.
  • Projects are hard-capped at 25 rows. projectsTruncated: true means the workspace has more; page the rest with GET /v1/projects.
An OAuth principal that is not a workspace admin sees only the projects it is individually assigned to — the same reach as GET /v1/projects, so the pack never names a project the caller would then be 403’d from. Errors are the /v1/workspaces/me set plus 403 scope_missing when the principal lacks workspace:read.

GET /v1/workspaces

Lists every workspace the caller can reach. For an OAuth token that is every Clerk organisation the consenting user is currently a member of (live membership), plus every client workspace billed to an agency they own; for an API key it is the single workspace the key is bound to. reach on each entry says which of the two applies.

Response

Field reference

name is empty only on an agency_owner entry whose Clerk organisation could not be resolved. The entry is still listed: an id you cannot discover is an id you cannot target.

GET /v1/team

The active workspace’s members: display name, email, org role, avatar, join date, and the projects each member is individually assigned to. roleLabel (added 2026-09-21) is the label the dashboard’s team page shows for role: Admin, Member or Client since 2026-09-22, when Scripe’s roles collapsed to those three. A membership still carrying a legacy slug (org:team_manager, org:content_assistant, org:personal_brand_team_insights) carries the label of the role it folds into (Admin, Admin, Member) until the migration moves it; role itself is unchanged, and org:personal_brand is the Member slug. Requires the workspace:read scope (same caveat as /v1/workspaces/context — OAuth tokens only, for now). The endpoint takes no workspace input: the target is always the workspace the request already authenticated against (Scripe-Workspace-Id for OAuth tokens). The field-by-field schema is TeamList in the OpenAPI reference tab.
Bounds, all of them visible in the response rather than silent:
  • Members are read one page deep (100). truncated: true with a larger totalCount means the workspace has more members than data carries.
  • Project references are capped at 25 distinct projects. projectsTruncated: true means refs past the cap were dropped from every member’s projects array; page the full set with GET /v1/projects.
  • Refs never exceed the caller’s own reach. An OAuth principal that is not a workspace admin sees only refs for projects it is itself assigned to, so the roster cannot name a project it would be 403’d from opening. Members themselves are always listed in full.
Credentials, tokens, and session material never appear in this response — it is a directory, not an account export.

Multi-workspace access

A single OAuth token can operate against any workspace the consenting user belongs to. Select the target per-request with the Scripe-Workspace-Id header (value = the org_* id from GET /v1/workspaces):
  • Default. Omit the header → the request runs against the consent-pinned (default) workspace. /v1/workspaces/me reflects the active workspace, so it changes with the header.
  • Live reach. Access is validated on every request against the user’s current Clerk membership (60 s cache) and, failing that, the billing-based agency-owner grant below. A header naming a workspace the user can reach by neither returns workspace_unavailable — and a workspace that does not exist, one they have left, and one their agency does not pay for all answer identically, so the error is no membership oracle.
  • Plan. Gating inherits the default workspace’s plan, so client workspaces on cheaper plans still work under an API-enabled token. A workspace an agency pays for carries the agency’s plan — see plan_not_eligible.
  • API keys are single-workspace. A Scripe-Workspace-Id header that disagrees with the key’s workspace is rejected with workspace_unavailable.
  • On MCP, the model can switch by itself. The switch_workspace tool moves an MCP connection’s active workspace without any header — same live reach rules.
  • One call across all of them. Analytics is the exception to one-workspace-per-call: GET /v1/analytics/cross-workspace/overview fans out over every reachable workspace and attributes each row. Everything else stays single-workspace by design.

Two ways a workspace is reachable

reach names the grant, and the two are not interchangeable: The second grant is the one the Scripe dashboard has always applied, and it exists because being added to a client’s Clerk organisation is optional: an agency can take over billing for a client workspace without its owner ever becoming a member of it. Until then the dashboard showed that workspace and the API did not. Inside a reachable workspace nothing else changes. An agency owner is treated as an admin there — the same rights the dashboard gives them, so they see every project — while a plain member still sees only the projects they are assigned to. An API key is always member: it is bound to its own workspace and cannot reach past it.

What’s NOT here (yet)

  • Switching workspaces with an API key. Not supported — API keys are bound to one workspace. Use an OAuth token (with Scripe-Workspace-Id) or mint a key in the target workspace.
  • Updating workspace metadata (renaming the workspace, changing the plan). Use the Scripe dashboard.