Skip to main content

Authentication

Every Kanban API request is authenticated with a workspace-scoped Personal Access Token (PAT) sent as an HTTP Bearer credential:

Authorization: Bearer <token>

There is no cookie, session, or OAuth flow in v1. The API is intended for server-side agents, CLIs, and native applications; it does not emit permissive cross-origin headers, so browser-based third-party apps cannot call it directly (that requires a future OAuth and CORS design — do not embed a long-lived PAT in frontend code).

The token model

  • Tokens are created in the FileTag web app under Settings → API tokens. You choose the scopes at creation time, and the requested scopes are shown before the token is issued.
  • The plaintext token (prefix ftag_pat_) is displayed once. Only its SHA-256 hash is stored server-side; a lost token cannot be recovered, only rotated.
  • Each token is bound to exactly one workspace. It represents you — the issuing user — in that workspace, and every permission check runs against your current membership and board access. A scope can never grant more than the represented user could do in the web app.
  • Tokens carrying a Kanban scope expire at most 90 days after issuance. Rotation mints a new plaintext token and revokes the replaced one atomically.
  • Creating or rotating a token with kanban:admin is a sensitive operation and requires recent re-authentication in the web app.

Sending the token

cURL:

curl -sS "$KANBAN_API_BASE_URL/account" \
-H "Authorization: Bearer $KANBAN_API_TOKEN"

JavaScript:

const baseUrl =
process.env.KANBAN_API_BASE_URL ?? "https://app.filetag.ai/api/kanban/v1";
const token = process.env.KANBAN_API_TOKEN;

async function main() {
const response = await fetch(`${baseUrl}/account`, {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
const payload = await response.json();
throw new Error(
`${payload.error.code}: ${payload.error.message} (request ${payload.error.request_id})`
);
}
console.log((await response.json()).data);
}

main().catch((error) => {
console.error(error);
process.exit(1);
});

Python:

import json
import os
import urllib.request

BASE_URL = os.environ.get(
"KANBAN_API_BASE_URL", "https://app.filetag.ai/api/kanban/v1"
)
TOKEN = os.environ["KANBAN_API_TOKEN"]

request = urllib.request.Request(
f"{BASE_URL}/account",
headers={"Authorization": f"Bearer {TOKEN}"},
)
with urllib.request.urlopen(request) as response:
print(json.load(response)["data"])

Authentication and authorization outcomes

ConditionResult
Missing, malformed, unknown, or revoked token401 unauthorized
Token user no longer belongs to the token workspace401 unauthorized
Valid token lacks the required scope403 insufficient_scope
Authenticated user lacks a management permission403 forbidden
Resource absent, outside the token workspace, or private404 not_found

Two points worth internalizing:

  • 401 responses include a WWW-Authenticate: Bearer header. Treat any 401 as "stop and re-issue the token" — it is never retryable as-is.
  • Inaccessible resources return 404 not_found, not 403. A board that exists in another workspace, or a private board you are not a member of, is indistinguishable from a board that does not exist. Do not use 404 to infer anything about resource existence. See Boards and visibility.

Verifying a token

GET /account is the recommended first call for any integration: it returns the represented user ID, the workspace, and the token's effective scopes, and requires only kanban:read. The workspace member directory (GET /members) then lets you resolve teammate user IDs for assignments and private-board membership without ever handling emails — it exposes only user_id, role, display_name, and avatar_url.

Handling tokens safely

  • Store tokens in a secret manager or environment variables — the examples on this site use KANBAN_API_TOKEN throughout. Never commit a token.
  • Give each integration its own token with the smallest sufficient scope, so one token can be rotated or revoked without breaking the others.
  • Revoke tokens you no longer use from the same Settings → API tokens page. Revocation is immediate: the next request with that token gets 401 unauthorized.