Authentication

Embed
Preview of the card
<a href="https://forumulate.com/reference/sdk-authentication"><img src="https://forumulate.com/reference/_api/public/orgs/046a9bc0-d530-43ae-9bae-af7945008cda/spaces/8042f004-e3d9-445f-b7a4-b6c1f86836e6/pages/c0294884-d248-4851-855f-8c7e4e7a0792/social-card.svg?v=3e7ae33eec8b" alt="Authentication" width="600" height="315"></a>

The API accepts two kinds of credentials, and the SDK supports both:

  • A Personal Access Token (PAT) — sent as Authorization: Bearer <token>. This is what server-to-server integrations use.

  • A session cookie — the first-party cookie set when you sign in to the console. Used only for same-origin browser code (credentials: true).

Creating a Personal Access Token

From the dashboard

Create and manage tokens in the console at /account/tokens. A token's plaintext value is shown once, at creation — copy it then; it is stored only as a hash and can never be displayed again. You can revoke a token at any time from the same page.

From the API

The same operation is available at POST /pats, which requires an authenticated session and an admin-scoped credential (issuing tokens is itself an admin action, so a merely-writable token cannot mint more tokens). The SDK exposes a helper:

const { token, pat } = await forumulate.auth.createToken({
  name: 'CI publisher',
  scopes: ['write'],
});
console.log(token); // "cft_..." — shown once

The underlying POST /pats endpoint accepts more fields than the helper types. Use client.typed to set them:

const { token } = await forumulate.typed('post', '/pats', {
  body: {
    name: 'One-space sync',
    scopes: ['write'],
    expiresInDays: 90,        // omit for a token that never expires on its own
    spaceIds: ['<space-uuid>'] // confine the token to specific spaces
  },
});
  • name — required. A human-readable label so a list of tokens is auditable later.

  • scopes — required, at least one. See below.

  • expiresInDays — optional, up to 3650. Omit for no automatic expiry.

  • spaceIds — optional, up to 50 space UUIDs. A token scoped to a space cannot even list the names of other spaces — which is what makes it safe to hand to a narrow integration. Omit for everywhere its owner can reach.

Tokens are opaque and carry a type prefix: PATs look like cft_…. (OAuth access tokens, cfo_…, authenticate the same way.)

Scopes

Scopes are a strict hierarchy — read ⊂ write ⊂ admin, so a broader scope satisfies a narrower requirement:

The default requirement is derived from the HTTP method (safe methods need read, everything else needs write); specific routes may demand admin. A request whose token lacks the required scope is rejected with 403 and code rbac.forbidden. Scopes apply to token auth only; browser session auth is governed by RBAC capabilities instead.

Passing the token to the client

import { ForumulateClient } from '@forumulate/sdk';

const forumulate = new ForumulateClient({
  baseUrl: 'https://forumulate.com/api',
  token: process.env.FORUMULATE_TOKEN, // "cft_..."
});

Every request the client makes then carries Authorization: Bearer <token>. Keep tokens in a secret store or environment variable — never commit them, and never ship a PAT in browser-delivered code (use credentials: true there instead).

The Forumulate teamUpdated