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:adminis 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
| Condition | Result |
|---|---|
| Missing, malformed, unknown, or revoked token | 401 unauthorized |
| Token user no longer belongs to the token workspace | 401 unauthorized |
| Valid token lacks the required scope | 403 insufficient_scope |
| Authenticated user lacks a management permission | 403 forbidden |
| Resource absent, outside the token workspace, or private | 404 not_found |
Two points worth internalizing:
401responses include aWWW-Authenticate: Bearerheader. Treat any401as "stop and re-issue the token" — it is never retryable as-is.- Inaccessible resources return
404 not_found, not403. 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 use404to 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_TOKENthroughout. 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.