Set up
You need one thing: your project’s API key, from the dashboard Overview page. It looks likeck_cloud_…. The client derives its own URL from the key,
so that’s the whole configuration.
Your first call
Install the client for your language and make one call. Every language takes the key and nothing else.pages.searchPage as your user “acme” and returns the
result. It’s always one request, POST /{tenant}/{plugin}/call/{op} with a
{ "args": {...} } body, so the language clients are thin wrappers over the
same shape.
What is a tenant?
A tenant is one of your users.withTenant("acme") (or with_tenant, Tenant,
tenant) picks which user a call acts as, so it uses that user’s connected
account. One runtime serves all your tenants at once. Building for a single
user? Pick one tenant id and forget about it.
The runtime rejects an empty tenant id rather than guessing, so a call is never
silently scoped to the wrong user.
Map your tenants
The runtime holds the tenants and which accounts each has connected. List them to line up against your own users:tenants gives you each tenant’s id and connected plugins, connectionStatus
gives the per-plugin auth state, and manage.permissions.get({ id }) reads a
permission grant (its scopes and approval status). All redact secrets: you see
that a tenant connected Notion, never their token. Reading a tenant’s stored
data rows directly, or pointing the runtime at your own database, comes with
bring-your-own-DB (coming soon).Connect a user’s account
Before a tenant can call Notion, they have to connect their Notion account. Corsair Cloud runs the OAuth. Create a connect link and send your user to it:Server vs. browser
The runtime has one contract and two ways to reach it:- From a server or agent. Use the client directly. It holds the key and calls the runtime, the path in every example above.
- From a browser (React). Browser code must never see the key. Stand up a
route in your own app that injects the bearer server-side.
corsair/connectbuilds that route from just the key:
app/api/corsair/[...path]/route.ts
<CorsairProvider baseURL="/api/corsair"> in the browser. The
provider only ever calls this same-origin route and never sees the key.
authorize is required: without it, corsairConnect throws at startup, since
anyone who can reach the route could otherwise invoke any tenant/plugin/operation
the project key allows. To intentionally run an open proxy, pass
allowUnauthenticated: true.
Then wrap your app in CorsairProvider and use useCorsair() to drive the
connect flow and read connection state. The key stays on your server the whole
time.
Type hints for your calls (TypeScript)
corsairCloud takes no plugin list, since the plugins live on the runtime, so
by default corsair.withTenant(t).notion.api… is typed as any. For
autocomplete, run the CLI once:
corsair-env.d.ts that TypeScript picks up, with
no plugin import to maintain. Coding agents can skip it and list operations with
pnpm corsair cloud list.