Authentication

Server integrations hold a client ID and secret and exchange them for short-lived access tokens with the OAuth 2.0 client_credentials grant. Interactive AI hosts connect as a signed-in user through delegated access instead.

Create API credentials

  1. Sign in at app.filemark.ca and open Developer. Creating credentials needs the owner role, or the admin role with the Manage developer API permission; other members see the list read-only.
  2. Create an API client and select only the scopes your integration needs.
  3. Copy the client secret when it is shown. It is never shown again.

Store the secret in a server-side secret manager. Never put it in browser code, browser-based tools like the interactive REST reference, source control, logs, URLs, or support messages.

If a secret is exposed, rotate it from the same page: rotation issues a replacement secret and keeps the client ID and scopes. Revoking a client is immediate and permanent; its tokens are refused on their next request.

Get an access token

  • resource is required. Send https://api.filemark.ca for a server integration; the trailing-slash form works too. MCP hosts may send the MCP server URL https://api.filemark.ca/mcp instead, but a token minted for that resource works only on the MCP server.
  • scope is required and lists the scopes your integration needs, written in full. Request mcp only if you will connect over MCP.
  • Authenticate with HTTP Basic or with the client_id and client_secret form fields, never both, and send each parameter once.
curl --request POST \
  --url https://api.filemark.ca/oauth2/token \
  --user "$FILEMARK_CLIENT_ID:$FILEMARK_CLIENT_SECRET" \
  --header "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=client_credentials" \
  --data-urlencode "resource=https://api.filemark.ca" \
  --data-urlencode "scope=https://api.filemark.ca/mcp https://api.filemark.ca/tax:compute"
import os
import requests

FILEMARK_CLIENT_ID = os.environ["FILEMARK_CLIENT_ID"]
FILEMARK_CLIENT_SECRET = os.environ["FILEMARK_CLIENT_SECRET"]

response = requests.post(
    "https://api.filemark.ca/oauth2/token",
    auth=(FILEMARK_CLIENT_ID, FILEMARK_CLIENT_SECRET),
    data={
        "grant_type": "client_credentials",
        "resource": "https://api.filemark.ca",
        "scope": "https://api.filemark.ca/mcp https://api.filemark.ca/tax:compute",
    },
)
response.raise_for_status()
print(response.json())
const FILEMARK_CLIENT_ID = process.env.FILEMARK_CLIENT_ID;
const FILEMARK_CLIENT_SECRET = process.env.FILEMARK_CLIENT_SECRET;

const response = await fetch("https://api.filemark.ca/oauth2/token", {
  method: "POST",
  headers: {
    Authorization: `Basic ${Buffer.from(`${FILEMARK_CLIENT_ID}:${FILEMARK_CLIENT_SECRET}`).toString("base64")}`,
    "Content-Type": "application/x-www-form-urlencoded",
  },
  body: new URLSearchParams({
    grant_type: "client_credentials",
    resource: "https://api.filemark.ca",
    scope: "https://api.filemark.ca/mcp https://api.filemark.ca/tax:compute",
  }),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());
{
  "access_token": "<access-token>",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "https://api.filemark.ca/mcp https://api.filemark.ca/tax:compute"
}

Tokens last up to 60 minutes.

Token endpoint errors

A failed exchange returns the OAuth 2.0 error shape, {"error": "...", "error_description": "..."}:

errorStatusCause
invalid_request400The form is malformed, a parameter is missing, duplicated, or unsupported, both authentication methods were sent, or the Content-Type is not application/x-www-form-urlencoded.
invalid_request413The form body exceeds 256 KiB.
invalid_client401The client ID and secret were rejected, or the client is unknown or not active.
invalid_scope400A requested scope is not a published scope or is not one this client was granted.
unsupported_grant_type400grant_type is not one the endpoint supports.
invalid_target400resource is not https://api.filemark.ca, its trailing-slash form, or https://api.filemark.ca/mcp.
temporarily_unavailable429 or 503The token-minting budget is exhausted (429) or the token service is unavailable (503). Wait the Retry-After seconds and retry.
Filemark | Authentication