Quickstart

You need a Filemark workspace where you are an owner, or an admin with the Manage developer API permission; only those roles can create API credentials.

1. Create API credentials

Create an API client with the tax:compute and clients:read scopes, and copy the secret when it is shown.

export FILEMARK_CLIENT_ID="<client-id>"
export FILEMARK_CLIENT_SECRET="<client-secret>"

2. Get an access token

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/tax:compute https://api.filemark.ca/clients:read"
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/tax:compute https://api.filemark.ca/clients:read",
    },
)
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/tax:compute https://api.filemark.ca/clients:read",
  }),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());
{
  "access_token": "<access-token>",
  "token_type": "Bearer",
  "expires_in": 900,
  "scope": "https://api.filemark.ca/tax:compute https://api.filemark.ca/clients:read"
}
export FILEMARK_ACCESS_TOKEN="<access-token>"

Mint a new token when expires_in runs out.

3. Read the computation catalog

curl https://api.filemark.ca/api/v1/computations \
  --header "Authorization: Bearer $FILEMARK_ACCESS_TOKEN"
import os
import requests

FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    "https://api.filemark.ca/api/v1/computations",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
)
response.raise_for_status()
print(response.json())
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const response = await fetch("https://api.filemark.ca/api/v1/computations", {
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());
{
  "data": {
    "batchTargets": ["schedule1", "schedule3", "schedule8", "schedule24", "part_i_tax"],
    "batchDependencies": {
      "schedule8": ["schedule23", "schedule24", "schedule6"]
    },
    "rolloverTargets": ["section-22", "section-86"]
  }
}

The real response lists every published target; this excerpt is abbreviated. batchDependencies names the targets that run automatically with the one you request.

4. Run a computation

This runs entirely from the inputs you send, so it works before your workspace holds a single client.

curl --request POST https://api.filemark.ca/api/v1/computations/batch \
  --header "Authorization: Bearer $FILEMARK_ACCESS_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "compute": [
      "schedule24"
    ],
    "inputs": {
      "taxYear": 2025,
      "schedule24": {
        "filingTriggers": [
          "incorporation"
        ],
        "operationCode": "01",
        "predecessors": [],
        "subsidiaries": []
      }
    }
  }'
import os
import requests

FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.post(
    "https://api.filemark.ca/api/v1/computations/batch",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
    json={
        "compute": [
            "schedule24",
        ],
        "inputs": {
            "taxYear": 2025,
            "schedule24": {
                "filingTriggers": [
                    "incorporation",
                ],
                "operationCode": "01",
                "predecessors": [],
                "subsidiaries": [],
            },
        },
    },
)
response.raise_for_status()
print(response.json())
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const response = await fetch("https://api.filemark.ca/api/v1/computations/batch", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "compute": [
      "schedule24"
    ],
    "inputs": {
      "taxYear": 2025,
      "schedule24": {
        "filingTriggers": [
          "incorporation"
        ],
        "operationCode": "01",
        "predecessors": [],
        "subsidiaries": []
      }
    }
  }),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());
{
  "data": {
    "results": {
      "schedule24": {
        "ready": false,
        "provisional": false,
        "warnings": []
      }
    }
  },
  "computeVersion": "<string>",
  "engineSchemaVersion": "<string>",
  "ratesVersion": "<string>",
  "timestamp": "2026-07-14T12:00:00Z"
}

Each result also carries the target's own output cells, listed under schedule24. To try a computation before wiring up credentials, sign in at app.filemark.ca and open API sandbox: it runs the same targets from your browser session and copies out the equivalent curl command.

5. List your clients

curl --get https://api.filemark.ca/api/v1/clients \
  --header "Authorization: Bearer $FILEMARK_ACCESS_TOKEN" \
  --data-urlencode "limit=5"
import os
import requests

FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    "https://api.filemark.ca/api/v1/clients",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
    params={
        "limit": "5",
    },
)
response.raise_for_status()
print(response.json())
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const url = new URL("https://api.filemark.ca/api/v1/clients");
url.searchParams.set("limit", "5");

const response = await fetch(url, {
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());
{
  "data": [
    {
      "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "name": "Acme Holdings Inc.",
      "createdAt": "2026-07-14T12:00:00Z",
      "updatedAt": "2026-07-14T12:00:00Z"
    }
  ],
  "pagination": {
    "limit": 5,
    "offset": 0,
    "total": 1,
    "hasMore": false
  }
}

Entities and tax years hang off the client; see Definitions.

Next steps

Filemark | Quickstart