REST reference

Every operation is under https://api.filemark.ca/api/v1 and takes Authorization: Bearer <access-token>; see Authentication. Shared rules for types, headers, and retries are under Conventions. Scopes are shortened here; send them in full.

ResourceOperationMethod and pathScope
ClientsList clientsGET /api/v1/clientsclients:read
ClientsGet a clientGET /api/v1/clients/{client_id}clients:read
ClientsList a client's entitiesGET /api/v1/clients/{client_id}/entitiesentities:read
EntitiesGet an entityGET /api/v1/entities/{entity_id}entities:read
EntitiesList an entity's tax yearsGET /api/v1/entities/{entity_id}/tax-yearstax-years:read
Tax yearsGet a tax yearGET /api/v1/tax-years/{tax_year_id}tax-years:read
SearchSearch engagement recordsGET /api/v1/searchengagements:read
EngagementsList engagementsGET /api/v1/engagementsengagements:read
EngagementsGet an engagementGET /api/v1/engagements/{engagement_id}engagements:read
EngagementsGet engagement contextGET /api/v1/engagements/{engagement_id}/contextengagements:read
EngagementsGet engagement historyGET /api/v1/engagements/{engagement_id}/historyengagements:read
EngagementsList engagement documentsGET /api/v1/engagements/{engagement_id}/documentsdocuments:read
EngagementsList engagement workpapersGET /api/v1/engagements/{engagement_id}/workpapersworkpapers:read
EngagementsGet engagement review summaryGET /api/v1/engagements/{engagement_id}/review-summaryreview:read
Engagement formsGet an engagement form catalogGET /api/v1/engagements/{engagement_id}/formsengagements:read
Saved tax dataGet a saved trial balanceGET /api/v1/engagements/{engagement_id}/trial-balancetax-data:read
Saved accountsGet a saved engagement accountGET /api/v1/engagements/{engagement_id}/accounts/{account_id}tax-data:read
Saved accountsList saved account adjustmentsGET /api/v1/engagements/{engagement_id}/accounts/{account_id}/adjustmentstax-data:read
Saved-state computationsCompute an engagement's saved state with cells replacedPOST /api/v1/engagements/{engagement_id}/computations/scenariotax-data:read + tax:compute
ComputationsList computation targetsGET /api/v1/computationstax:compute
ComputationsGet a computation target contractGET /api/v1/computations/targets/{target_id}tax:compute
ComputationsCompute tax schedulesPOST /api/v1/computations/batchtax:compute
ComputationsCompute a rollover or reorganizationPOST /api/v1/computations/rollovers/{target}tax:compute

An engagement ID is a tax year's UUID; see Definitions. Unknown IDs and IDs outside your organization return 404.

Pagination

GET /clients, /engagements/{id}/documents, and /engagements/{id}/workpapers use bounded offset pagination. limit defaults to 50 and accepts 1 through 200. offset is zero-based and accepts 0 through 100,000. Follow pagination.hasMore and advance offset by the number of returned rows.

The client-to-entity, entity-to-tax-year, and GET /engagements collections use opaque keyset cursors. Pass the returned pagination.nextCursor unchanged as the next request's cursor; do not decode it or reuse it under a different parent resource. A null nextCursor marks the final page.

GET /engagements/{id}/trial-balance uses an opaque snapshot-bound cursor, and every page must come from the same saved projection. A 409 saying the trial balance changed means that projection moved: discard the cursor and restart from the first page. A 409 saying the saved trial balance cannot be represented is a stored-state problem that restarting will not fix. A malformed cursor, or one from another engagement, is a 400.

Operation reference

Generated from the published OpenAPI schema (version 1.2.0). A path variable such as $CLIENT_ID is a UUID from an earlier read. Response bodies show the shape only: values in angle brackets are placeholders, an enum lists its alternatives inline, and a computation result also carries the target's output cells.

List clients

GET /api/v1/clients

List clients using tenant identity from the verified principal only.

Scope: clients:read.

Request

curl --get https://api.filemark.ca/api/v1/clients \
  --header "Authorization: Bearer $FILEMARK_ACCESS_TOKEN" \
  --data-urlencode "limit=50"
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": "50",
    },
)
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", "50");

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());

Parameters

ParameterInTypeRequiredDescription
limitqueryinteger, 1 to 200, default 50noPage size (1-200).
offsetqueryinteger, 0 to 100000, default 0noZero-based row offset (maximum 100,000).

Response

200. One page of the organization's clients.

{
  "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": 0,
    "offset": 0,
    "total": 0,
    "hasMore": false
  }
}

Response fields

FieldTypeAlways presentDescription
dataarray of objectsyes
data[].idstring (uuid)yesStable UUID of the client.
data[].namestringyesClient display name.
data[].createdAtstring (date-time)yesISO-8601 creation timestamp (UTC).
data[].updatedAtstring (date-time)yesISO-8601 last-modified timestamp (UTC).
paginationobjectyesOffset pagination retained for the original client-list contract.
pagination.limitintegeryesPage size actually applied (1-200).
pagination.offsetintegeryesZero-based row offset (max 100,000).
pagination.totalintegeryesTotal matching resources in the organization.
pagination.hasMorebooleanyesTrue when more rows exist past this page.

Errors

The shared codes only; see error codes.

Get a client

GET /api/v1/clients/{client_id}

Get one client without revealing cross-organization identifiers.

Scope: clients:read.

Request

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

CLIENT_ID = "<client-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/clients/{CLIENT_ID}",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
)
response.raise_for_status()
print(response.json())
const CLIENT_ID = "<client-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const response = await fetch(`https://api.filemark.ca/api/v1/clients/${CLIENT_ID}`, {
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Parameters

ParameterInTypeRequiredDescription
client_idpathstring (uuid)yes

Response

200. The requested client.

{
  "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
  "name": "Acme Holdings Inc.",
  "createdAt": "2026-07-14T12:00:00Z",
  "updatedAt": "2026-07-14T12:00:00Z"
}

Response fields

FieldTypeAlways presentDescription
idstring (uuid)yesStable UUID of the client.
namestringyesClient display name.
createdAtstring (date-time)yesISO-8601 creation timestamp (UTC).
updatedAtstring (date-time)yesISO-8601 last-modified timestamp (UTC).

Errors

The shared codes only; see error codes.

List a client's entities

GET /api/v1/clients/{client_id}/entities

List entities under an organization-owned client.

Scope: entities:read.

Request

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

CLIENT_ID = "<client-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/clients/{CLIENT_ID}/entities",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
    params={
        "limit": "50",
    },
)
response.raise_for_status()
print(response.json())
const CLIENT_ID = "<client-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const url = new URL(`https://api.filemark.ca/api/v1/clients/${CLIENT_ID}/entities`);
url.searchParams.set("limit", "50");

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());

Parameters

ParameterInTypeRequiredDescription
client_idpathstring (uuid)yes
limitqueryinteger, 1 to 200, default 50noPage size (1-200).
cursorquerynullable string, 1 to 4096 charactersnoOpaque cursor returned by the preceding page.

Response

200. One cursor-paginated page of the client's entities.

{
  "data": [
    {
      "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "clientId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "name": "<string>",
      "legalName": "<string>",
      "corporationNumber": "<string>",
      "businessNumber": "<string>",
      "naicsCode": "<string>",
      "dissolvedAt": "2025-12-31",
      "incorporationJurisdiction": "<string>",
      "incorporationDate": "2025-12-31"
    }
  ],
  "pagination": {
    "limit": 0,
    "nextCursor": "<string>",
    "hasMore": false
  }
}

Response fields

FieldTypeAlways presentDescription
dataarray of objectsyes
data[].idstring (uuid)yesStable UUID of the entity.
data[].clientIdstring (uuid)yesUUID of the entity's parent client.
data[].namestringyesEntity display name.
data[].legalNamenullable stringnoRegistered legal name, when known.
data[].corporationNumbernullable stringnoCorporate registry number, when known.
data[].businessNumbernullable stringnoCanadian business number, when known.
data[].naicsCodenullable stringnoNAICS industry code, when assigned.
data[].dissolvedAtnullable string (date)noEntity dissolution date, when applicable.
data[].incorporationJurisdictionnullable stringnoCorporate-law jurisdiction the corporation is incorporated or continued under: 'CA' (federal CBCA) or a two-letter province/territory code. Changes only by continuance (ITA s.250(5.1)), never by fiscal period. This is NOT the provincial jurisdiction the corporation is taxed in, that is the per-tax-year permanent-establishment set (ITR Reg. 400(2)/402(3)) reported on Schedule 5. Null when not recorded, which is also the correct state for a corporation incorporated outside Canada.
data[].incorporationDatenullable string (date)noDate the current incorporationJurisdiction took effect: original incorporation, or the most recent continuance into that jurisdiction. Null when not recorded.
paginationobjectyesOpaque keyset pagination for new v1 collection endpoints.
pagination.limitintegeryesPage size actually applied (1-200).
pagination.nextCursornullable stringnoOpaque cursor for the next page; null on the final page.
pagination.hasMorebooleanyesTrue when another page is available.

Errors

The shared codes only; see error codes.

Get an entity

GET /api/v1/entities/{entity_id}

Get one entity without revealing cross-organization identifiers.

Scope: entities:read.

Request

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

ENTITY_ID = "<entity-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/entities/{ENTITY_ID}",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
)
response.raise_for_status()
print(response.json())
const ENTITY_ID = "<entity-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const response = await fetch(`https://api.filemark.ca/api/v1/entities/${ENTITY_ID}`, {
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Parameters

ParameterInTypeRequiredDescription
entity_idpathstring (uuid)yes

Response

200. The requested entity.

{
  "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
  "clientId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
  "name": "<string>",
  "legalName": "<string>",
  "corporationNumber": "<string>",
  "businessNumber": "<string>",
  "naicsCode": "<string>",
  "dissolvedAt": "2025-12-31",
  "incorporationJurisdiction": "<string>",
  "incorporationDate": "2025-12-31"
}

Response fields

FieldTypeAlways presentDescription
idstring (uuid)yesStable UUID of the entity.
clientIdstring (uuid)yesUUID of the entity's parent client.
namestringyesEntity display name.
legalNamenullable stringnoRegistered legal name, when known.
corporationNumbernullable stringnoCorporate registry number, when known.
businessNumbernullable stringnoCanadian business number, when known.
naicsCodenullable stringnoNAICS industry code, when assigned.
dissolvedAtnullable string (date)noEntity dissolution date, when applicable.
incorporationJurisdictionnullable stringnoCorporate-law jurisdiction the corporation is incorporated or continued under: 'CA' (federal CBCA) or a two-letter province/territory code. Changes only by continuance (ITA s.250(5.1)), never by fiscal period. This is NOT the provincial jurisdiction the corporation is taxed in, that is the per-tax-year permanent-establishment set (ITR Reg. 400(2)/402(3)) reported on Schedule 5. Null when not recorded, which is also the correct state for a corporation incorporated outside Canada.
incorporationDatenullable string (date)noDate the current incorporationJurisdiction took effect: original incorporation, or the most recent continuance into that jurisdiction. Null when not recorded.

Errors

The shared codes only; see error codes.

List an entity's tax years

GET /api/v1/entities/{entity_id}/tax-years

List tax years under an organization-owned entity.

Scope: tax-years:read.

Request

curl --get https://api.filemark.ca/api/v1/entities/$ENTITY_ID/tax-years \
  --header "Authorization: Bearer $FILEMARK_ACCESS_TOKEN" \
  --data-urlencode "limit=50"
import os
import requests

ENTITY_ID = "<entity-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/entities/{ENTITY_ID}/tax-years",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
    params={
        "limit": "50",
    },
)
response.raise_for_status()
print(response.json())
const ENTITY_ID = "<entity-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const url = new URL(`https://api.filemark.ca/api/v1/entities/${ENTITY_ID}/tax-years`);
url.searchParams.set("limit", "50");

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());

Parameters

ParameterInTypeRequiredDescription
entity_idpathstring (uuid)yes
limitqueryinteger, 1 to 200, default 50noPage size (1-200).
cursorquerynullable string, 1 to 4096 charactersnoOpaque cursor returned by the preceding page.

Response

200. One cursor-paginated page of the entity's tax years.

{
  "data": [
    {
      "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "entityId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "clientId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "yearEnd": "2025-12-31",
      "periodStart": "2025-12-31",
      "status": "<in_progress | review | complete>",
      "source": "<prepared | imported>",
      "engagementType": "<compilation | review | audit | tax_only>",
      "priorYearTaxYearId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "createdAt": "2026-07-14T12:00:00Z",
      "lastModifiedAt": "2026-07-14T12:00:00Z"
    }
  ],
  "pagination": {
    "limit": 0,
    "nextCursor": "<string>",
    "hasMore": false
  }
}

Response fields

FieldTypeAlways presentDescription
dataarray of objectsyes
data[].idstring (uuid)yesStable UUID of the tax-year engagement.
data[].entityIdstring (uuid)yesUUID of the parent entity.
data[].clientIdstring (uuid)yesUUID of the parent client.
data[].yearEndstring (date)yesFiscal year-end date.
data[].periodStartnullable string (date)noFiscal period start date; null only for legacy records.
data[].statusone of in_progress, review, completeyesCurrent engagement workflow status.
data[].sourceone of prepared, importedyesPrepared binder or imported prior-year reference.
data[].engagementTypenullable one of compilation, review, audit, tax_onlynoEngagement service type, when assigned.
data[].priorYearTaxYearIdnullable string (uuid)noLinked prior tax year used for comparatives, when present.
data[].createdAtstring (date-time)yesISO-8601 creation timestamp (UTC).
data[].lastModifiedAtstring (date-time)yesISO-8601 last-modified timestamp (UTC).
paginationobjectyesOpaque keyset pagination for new v1 collection endpoints.
pagination.limitintegeryesPage size actually applied (1-200).
pagination.nextCursornullable stringnoOpaque cursor for the next page; null on the final page.
pagination.hasMorebooleanyesTrue when another page is available.

Errors

The shared codes only; see error codes.

Get a tax year

GET /api/v1/tax-years/{tax_year_id}

Get one tax year without revealing cross-organization identifiers.

Scope: tax-years:read.

Request

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

TAX_YEAR_ID = "<tax-year-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/tax-years/{TAX_YEAR_ID}",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
)
response.raise_for_status()
print(response.json())
const TAX_YEAR_ID = "<tax-year-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const response = await fetch(`https://api.filemark.ca/api/v1/tax-years/${TAX_YEAR_ID}`, {
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Parameters

ParameterInTypeRequiredDescription
tax_year_idpathstring (uuid)yes

Response

200. The requested tax-year engagement.

{
  "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
  "entityId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
  "clientId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
  "yearEnd": "2025-12-31",
  "periodStart": "2025-12-31",
  "status": "<in_progress | review | complete>",
  "source": "<prepared | imported>",
  "engagementType": "<compilation | review | audit | tax_only>",
  "priorYearTaxYearId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
  "createdAt": "2026-07-14T12:00:00Z",
  "lastModifiedAt": "2026-07-14T12:00:00Z"
}

Response fields

FieldTypeAlways presentDescription
idstring (uuid)yesStable UUID of the tax-year engagement.
entityIdstring (uuid)yesUUID of the parent entity.
clientIdstring (uuid)yesUUID of the parent client.
yearEndstring (date)yesFiscal year-end date.
periodStartnullable string (date)noFiscal period start date; null only for legacy records.
statusone of in_progress, review, completeyesCurrent engagement workflow status.
sourceone of prepared, importedyesPrepared binder or imported prior-year reference.
engagementTypenullable one of compilation, review, audit, tax_onlynoEngagement service type, when assigned.
priorYearTaxYearIdnullable string (uuid)noLinked prior tax year used for comparatives, when present.
createdAtstring (date-time)yesISO-8601 creation timestamp (UTC).
lastModifiedAtstring (date-time)yesISO-8601 last-modified timestamp (UTC).

Errors

The shared codes only; see error codes.

Search engagement records

GET /api/v1/search

Searches current organization-owned engagements by client name, entity name, fiscal year, or year-end. Returns safe engagement metadata only; accounts, financials, saved forms, classified reports, documents, workpapers, and people are excluded. A no-match result is a successful response and ambiguity is reported explicitly.

Scope: engagements:read.

Request

curl --get https://api.filemark.ca/api/v1/search \
  --header "Authorization: Bearer $FILEMARK_ACCESS_TOKEN" \
  --data-urlencode "q=<q>" \
  --data-urlencode "limit=10"
import os
import requests

FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    "https://api.filemark.ca/api/v1/search",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
    params={
        "q": "<q>",
        "limit": "10",
    },
)
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/search");
url.searchParams.set("q", "<q>");
url.searchParams.set("limit", "10");

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());

Parameters

ParameterInTypeRequiredDescription
qquerystring, 2 to 80 charactersyesTwo to eighty characters and at most six whitespace-separated terms. ILIKE wildcard characters are matched literally.
year_endquerynullable string (date)noOptional exact taxation-year end date.
statusquerynullable one of in_progress, review, completenoOptional workflow-status filter.
limitqueryinteger, 1 to 25, default 10noShortlist size (1-25).

Response

200. Current engagement matches and their explicit resolution state.

{
  "query": "<string>",
  "resolution": "<no_match | unique | ambiguous>",
  "data": [
    {
      "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "client": {
        "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
        "name": "<string>",
        "legalName": "<string>"
      },
      "entity": {
        "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
        "name": "<string>",
        "legalName": "<string>"
      },
      "yearEnd": "2025-12-31",
      "periodStart": "2025-12-31",
      "status": "<in_progress | review | complete>",
      "source": "<prepared | imported>",
      "engagementType": "<compilation | review | audit | tax_only>",
      "priorYearEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "isLocked": false,
      "lifecycle": {
        "filedAt": "2026-07-14T12:00:00Z",
        "revisionNumber": 1,
        "parentEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
        "amendedByEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f"
      },
      "createdAt": "2026-07-14T12:00:00Z",
      "updatedAt": "2026-07-14T12:00:00Z"
    }
  ],
  "pagination": {
    "limit": 1,
    "hasMore": false
  }
}

Response fields

FieldTypeAlways presentDescription
querystring, 2 to 80 charactersyes
resolutionone of no_match, unique, ambiguousyes
dataarray of objects, up to 25 itemsyes
data[].idstring (uuid)yes
data[].clientobjectyesSafe identity fields for an engagement's client or entity.
data[].client.idstring (uuid)yes
data[].client.namestringyes
data[].client.legalNamenullable stringno
data[].entityobjectyesSafe identity fields for an engagement's client or entity.
data[].entity.idstring (uuid)yes
data[].entity.namestringyes
data[].entity.legalNamenullable stringno
data[].yearEndstring (date)yes
data[].periodStartnullable string (date)no
data[].statusone of in_progress, review, completeyes
data[].sourceone of prepared, importedyes
data[].engagementTypenullable one of compilation, review, audit, tax_onlyno
data[].priorYearEngagementIdnullable string (uuid)no
data[].isLockedbooleanyes
data[].lifecycleobjectyesNon-sensitive return lifecycle metadata.
data[].lifecycle.filedAtnullable string (date-time)no
data[].lifecycle.revisionNumberinteger, at least 1yes
data[].lifecycle.parentEngagementIdnullable string (uuid)no
data[].lifecycle.amendedByEngagementIdnullable string (uuid)no
data[].createdAtstring (date-time)yes
data[].updatedAtstring (date-time)yes
paginationobjectyesMetadata for one bounded search shortlist.
pagination.limitinteger, 1 to 25yesResult limit actually applied.
pagination.hasMorebooleanyesTrue when additional matching engagements were omitted.

Errors

Beyond the shared codes in error codes:

  • 409: A matched engagement revision is inconsistent.

List engagements

GET /api/v1/engagements

Discover engagements without exposing stored financial or tax payloads.

Scope: engagements:read.

Request

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

FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    "https://api.filemark.ca/api/v1/engagements",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
    params={
        "limit": "50",
    },
)
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/engagements");
url.searchParams.set("limit", "50");

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());

Parameters

ParameterInTypeRequiredDescription
client_idquerynullable string (uuid)noOptional organization-owned client filter.
entity_idquerynullable string (uuid)noOptional organization-owned legal-entity filter.
year_endquerynullable string (date)noOptional exact taxation-year end date.
statusquerynullable one of in_progress, review, completenoOptional workflow-status filter.
limitqueryinteger, 1 to 200, default 50noPage size (1-200).
cursorquerynullable string, 1 to 4096 charactersnoOpaque cursor returned by the preceding page.

Response

200. One newest-first page of safe engagement identity and lifecycle metadata.

{
  "data": [
    {
      "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "client": {
        "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
        "name": "<string>",
        "legalName": "<string>"
      },
      "entity": {
        "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
        "name": "<string>",
        "legalName": "<string>"
      },
      "yearEnd": "2025-12-31",
      "periodStart": "2025-12-31",
      "status": "<in_progress | review | complete>",
      "source": "<prepared | imported>",
      "engagementType": "<compilation | review | audit | tax_only>",
      "priorYearEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "isLocked": false,
      "lifecycle": {
        "filedAt": "2026-07-14T12:00:00Z",
        "revisionNumber": 1,
        "parentEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
        "amendedByEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f"
      },
      "createdAt": "2026-07-14T12:00:00Z",
      "updatedAt": "2026-07-14T12:00:00Z"
    }
  ],
  "pagination": {
    "limit": 0,
    "nextCursor": "<string>",
    "hasMore": false
  }
}

Response fields

FieldTypeAlways presentDescription
dataarray of objectsyes
data[].idstring (uuid)yes
data[].clientobjectyesSafe identity fields for an engagement's client or entity.
data[].client.idstring (uuid)yes
data[].client.namestringyes
data[].client.legalNamenullable stringno
data[].entityobjectyesSafe identity fields for an engagement's client or entity.
data[].entity.idstring (uuid)yes
data[].entity.namestringyes
data[].entity.legalNamenullable stringno
data[].yearEndstring (date)yes
data[].periodStartnullable string (date)no
data[].statusone of in_progress, review, completeyes
data[].sourceone of prepared, importedyes
data[].engagementTypenullable one of compilation, review, audit, tax_onlyno
data[].priorYearEngagementIdnullable string (uuid)no
data[].isLockedbooleanyes
data[].lifecycleobjectyesNon-sensitive return lifecycle metadata.
data[].lifecycle.filedAtnullable string (date-time)no
data[].lifecycle.revisionNumberinteger, at least 1yes
data[].lifecycle.parentEngagementIdnullable string (uuid)no
data[].lifecycle.amendedByEngagementIdnullable string (uuid)no
data[].createdAtstring (date-time)yes
data[].updatedAtstring (date-time)yes
paginationobjectyesOpaque keyset pagination for new v1 collection endpoints.
pagination.limitintegeryesPage size actually applied (1-200).
pagination.nextCursornullable stringnoOpaque cursor for the next page; null on the final page.
pagination.hasMorebooleanyesTrue when another page is available.

Errors

The shared codes only; see error codes.

Get an engagement

GET /api/v1/engagements/{engagement_id}

Read one tax-year engagement without its financial/tax payloads.

Scope: engagements:read.

Request

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

ENGAGEMENT_ID = "<engagement-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/engagements/{ENGAGEMENT_ID}",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
)
response.raise_for_status()
print(response.json())
const ENGAGEMENT_ID = "<engagement-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const response = await fetch(`https://api.filemark.ca/api/v1/engagements/${ENGAGEMENT_ID}`, {
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Parameters

ParameterInTypeRequiredDescription
engagement_idpathstring (uuid)yes

Response

200. Safe identity, period, status, and lifecycle metadata.

{
  "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
  "client": {
    "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "name": "<string>",
    "legalName": "<string>"
  },
  "entity": {
    "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "name": "<string>",
    "legalName": "<string>"
  },
  "yearEnd": "2025-12-31",
  "periodStart": "2025-12-31",
  "status": "<in_progress | review | complete>",
  "source": "<prepared | imported>",
  "engagementType": "<compilation | review | audit | tax_only>",
  "priorYearEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
  "isLocked": false,
  "lifecycle": {
    "filedAt": "2026-07-14T12:00:00Z",
    "revisionNumber": 1,
    "parentEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "amendedByEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f"
  },
  "createdAt": "2026-07-14T12:00:00Z",
  "updatedAt": "2026-07-14T12:00:00Z"
}

Response fields

FieldTypeAlways presentDescription
idstring (uuid)yes
clientobjectyesSafe identity fields for an engagement's client or entity.
client.idstring (uuid)yes
client.namestringyes
client.legalNamenullable stringno
entityobjectyesSafe identity fields for an engagement's client or entity.
entity.idstring (uuid)yes
entity.namestringyes
entity.legalNamenullable stringno
yearEndstring (date)yes
periodStartnullable string (date)no
statusone of in_progress, review, completeyes
sourceone of prepared, importedyes
engagementTypenullable one of compilation, review, audit, tax_onlyno
priorYearEngagementIdnullable string (uuid)no
isLockedbooleanyes
lifecycleobjectyesNon-sensitive return lifecycle metadata.
lifecycle.filedAtnullable string (date-time)no
lifecycle.revisionNumberinteger, at least 1yes
lifecycle.parentEngagementIdnullable string (uuid)no
lifecycle.amendedByEngagementIdnullable string (uuid)no
createdAtstring (date-time)yes
updatedAtstring (date-time)yes

Errors

The shared codes only; see error codes.

Get engagement context

GET /api/v1/engagements/{engagement_id}/context

Resolve one engagement revision without loading saved tax data.

Scope: engagements:read.

Request

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

ENGAGEMENT_ID = "<engagement-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/engagements/{ENGAGEMENT_ID}/context",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
)
response.raise_for_status()
print(response.json())
const ENGAGEMENT_ID = "<engagement-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const response = await fetch(`https://api.filemark.ca/api/v1/engagements/${ENGAGEMENT_ID}/context`, {
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Parameters

ParameterInTypeRequiredDescription
engagement_idpathstring (uuid)yes

Response

200. Requested and current amendment revisions using safe engagement projections.

{
  "requestedEngagement": {
    "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "client": {
      "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "name": "<string>",
      "legalName": "<string>"
    },
    "entity": {
      "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "name": "<string>",
      "legalName": "<string>"
    },
    "yearEnd": "2025-12-31",
    "periodStart": "2025-12-31",
    "status": "<in_progress | review | complete>",
    "source": "<prepared | imported>",
    "engagementType": "<compilation | review | audit | tax_only>",
    "priorYearEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "isLocked": false,
    "lifecycle": {
      "filedAt": "2026-07-14T12:00:00Z",
      "revisionNumber": 1,
      "parentEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "amendedByEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f"
    },
    "createdAt": "2026-07-14T12:00:00Z",
    "updatedAt": "2026-07-14T12:00:00Z"
  },
  "currentEngagement": {
    "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "client": {
      "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "name": "<string>",
      "legalName": "<string>"
    },
    "entity": {
      "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "name": "<string>",
      "legalName": "<string>"
    },
    "yearEnd": "2025-12-31",
    "periodStart": "2025-12-31",
    "status": "<in_progress | review | complete>",
    "source": "<prepared | imported>",
    "engagementType": "<compilation | review | audit | tax_only>",
    "priorYearEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "isLocked": false,
    "lifecycle": {
      "filedAt": "2026-07-14T12:00:00Z",
      "revisionNumber": 1,
      "parentEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "amendedByEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f"
    },
    "createdAt": "2026-07-14T12:00:00Z",
    "updatedAt": "2026-07-14T12:00:00Z"
  },
  "revision": {
    "rootEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "previousEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "nextEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "currentEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "isCurrent": false
  }
}

Response fields

FieldTypeAlways presentDescription
requestedEngagementobjectyesOne tax-year engagement, without financial or tax-return payloads.
requestedEngagement.idstring (uuid)yes
requestedEngagement.clientobjectyesSafe identity fields for an engagement's client or entity.
requestedEngagement.client.idstring (uuid)yes
requestedEngagement.client.namestringyes
requestedEngagement.client.legalNamenullable stringno
requestedEngagement.entityobjectyesSafe identity fields for an engagement's client or entity.
requestedEngagement.entity.idstring (uuid)yes
requestedEngagement.entity.namestringyes
requestedEngagement.entity.legalNamenullable stringno
requestedEngagement.yearEndstring (date)yes
requestedEngagement.periodStartnullable string (date)no
requestedEngagement.statusone of in_progress, review, completeyes
requestedEngagement.sourceone of prepared, importedyes
requestedEngagement.engagementTypenullable one of compilation, review, audit, tax_onlyno
requestedEngagement.priorYearEngagementIdnullable string (uuid)no
requestedEngagement.isLockedbooleanyes
requestedEngagement.lifecycleobjectyesNon-sensitive return lifecycle metadata.
requestedEngagement.lifecycle.filedAtnullable string (date-time)no
requestedEngagement.lifecycle.revisionNumberinteger, at least 1yes
requestedEngagement.lifecycle.parentEngagementIdnullable string (uuid)no
requestedEngagement.lifecycle.amendedByEngagementIdnullable string (uuid)no
requestedEngagement.createdAtstring (date-time)yes
requestedEngagement.updatedAtstring (date-time)yes
currentEngagementobjectyesOne tax-year engagement, without financial or tax-return payloads.
currentEngagement.idstring (uuid)yes
currentEngagement.clientobjectyesSafe identity fields for an engagement's client or entity.
currentEngagement.client.idstring (uuid)yes
currentEngagement.client.namestringyes
currentEngagement.client.legalNamenullable stringno
currentEngagement.entityobjectyesSafe identity fields for an engagement's client or entity.
currentEngagement.entity.idstring (uuid)yes
currentEngagement.entity.namestringyes
currentEngagement.entity.legalNamenullable stringno
currentEngagement.yearEndstring (date)yes
currentEngagement.periodStartnullable string (date)no
currentEngagement.statusone of in_progress, review, completeyes
currentEngagement.sourceone of prepared, importedyes
currentEngagement.engagementTypenullable one of compilation, review, audit, tax_onlyno
currentEngagement.priorYearEngagementIdnullable string (uuid)no
currentEngagement.isLockedbooleanyes
currentEngagement.lifecycleobjectyesNon-sensitive return lifecycle metadata.
currentEngagement.lifecycle.filedAtnullable string (date-time)no
currentEngagement.lifecycle.revisionNumberinteger, at least 1yes
currentEngagement.lifecycle.parentEngagementIdnullable string (uuid)no
currentEngagement.lifecycle.amendedByEngagementIdnullable string (uuid)no
currentEngagement.createdAtstring (date-time)yes
currentEngagement.updatedAtstring (date-time)yes
revisionobjectyesSafe amendment-chain relationships for one requested engagement.
revision.rootEngagementIdstring (uuid)yes
revision.previousEngagementIdnullable string (uuid)no
revision.nextEngagementIdnullable string (uuid)no
revision.currentEngagementIdstring (uuid)yes
revision.isCurrentbooleanyes

Errors

Beyond the shared codes in error codes:

  • 409: The persisted amendment chain is inconsistent.

Get engagement history

GET /api/v1/engagements/{engagement_id}/history

Read amendment metadata only; raw change history remains private.

Scope: engagements:read.

Request

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

ENGAGEMENT_ID = "<engagement-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/engagements/{ENGAGEMENT_ID}/history",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
)
response.raise_for_status()
print(response.json())
const ENGAGEMENT_ID = "<engagement-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const response = await fetch(`https://api.filemark.ca/api/v1/engagements/${ENGAGEMENT_ID}/history`, {
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Parameters

ParameterInTypeRequiredDescription
engagement_idpathstring (uuid)yes

Response

200. A bounded, validated amendment chain without edit diffs or user identities.

{
  "engagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
  "currentEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
  "revisions": [
    {
      "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "client": {
        "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
        "name": "<string>",
        "legalName": "<string>"
      },
      "entity": {
        "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
        "name": "<string>",
        "legalName": "<string>"
      },
      "yearEnd": "2025-12-31",
      "periodStart": "2025-12-31",
      "status": "<in_progress | review | complete>",
      "source": "<prepared | imported>",
      "engagementType": "<compilation | review | audit | tax_only>",
      "priorYearEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "isLocked": false,
      "lifecycle": {
        "filedAt": "2026-07-14T12:00:00Z",
        "revisionNumber": 1,
        "parentEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
        "amendedByEngagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f"
      },
      "createdAt": "2026-07-14T12:00:00Z",
      "updatedAt": "2026-07-14T12:00:00Z"
    }
  ]
}

Response fields

FieldTypeAlways presentDescription
engagementIdstring (uuid)yes
currentEngagementIdstring (uuid)yes
revisionsarray of objects, 1 to 100 itemsyes
revisions[].idstring (uuid)yes
revisions[].clientobjectyesSafe identity fields for an engagement's client or entity.
revisions[].client.idstring (uuid)yes
revisions[].client.namestringyes
revisions[].client.legalNamenullable stringno
revisions[].entityobjectyesSafe identity fields for an engagement's client or entity.
revisions[].entity.idstring (uuid)yes
revisions[].entity.namestringyes
revisions[].entity.legalNamenullable stringno
revisions[].yearEndstring (date)yes
revisions[].periodStartnullable string (date)no
revisions[].statusone of in_progress, review, completeyes
revisions[].sourceone of prepared, importedyes
revisions[].engagementTypenullable one of compilation, review, audit, tax_onlyno
revisions[].priorYearEngagementIdnullable string (uuid)no
revisions[].isLockedbooleanyes
revisions[].lifecycleobjectyesNon-sensitive return lifecycle metadata.
revisions[].lifecycle.filedAtnullable string (date-time)no
revisions[].lifecycle.revisionNumberinteger, at least 1yes
revisions[].lifecycle.parentEngagementIdnullable string (uuid)no
revisions[].lifecycle.amendedByEngagementIdnullable string (uuid)no
revisions[].createdAtstring (date-time)yes
revisions[].updatedAtstring (date-time)yes

Errors

Beyond the shared codes in error codes:

  • 409: The persisted amendment chain is inconsistent.

List engagement documents

GET /api/v1/engagements/{engagement_id}/documents

List metadata only; storage paths and file contents are never returned.

Scope: documents:read.

Request

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

ENGAGEMENT_ID = "<engagement-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/engagements/{ENGAGEMENT_ID}/documents",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
    params={
        "limit": "50",
    },
)
response.raise_for_status()
print(response.json())
const ENGAGEMENT_ID = "<engagement-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const url = new URL(`https://api.filemark.ca/api/v1/engagements/${ENGAGEMENT_ID}/documents`);
url.searchParams.set("limit", "50");

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());

Parameters

ParameterInTypeRequiredDescription
engagement_idpathstring (uuid)yes
limitqueryinteger, 1 to 200, default 50noPage size (1-200).
offsetqueryinteger, 0 to 100000, default 0noZero-based row offset (maximum 100,000).

Response

200. One page of safe document-registry metadata.

{
  "data": [
    {
      "id": "<string>",
      "fileName": "<string>",
      "kind": "<gl | fs | workpaper | supporting | tb-current | tb-prior | tb-classification | gifi-export | prior-return | portal-upload | evidence>",
      "source": "<onboarding | manual | portal | connector | unknown>",
      "uploadedAt": "2026-07-14T12:00:00Z"
    }
  ],
  "pagination": {
    "limit": 1,
    "offset": 0,
    "total": 0,
    "hasMore": false
  }
}

Response fields

FieldTypeAlways presentDescription
dataarray of objectsyes
data[].idstring, 1 to 256 charactersyes
data[].fileNamestring, 1 to 512 charactersyes
data[].kindone of gl, fs, workpaper, supporting, tb-current, tb-prior, tb-classification, gifi-export, prior-return, portal-upload, evidenceyes
data[].sourceone of onboarding, manual, portal, connector, unknownyes
data[].uploadedAtnullable string (date-time)no
paginationobjectyesBounded offset-pagination metadata.
pagination.limitinteger, 1 to 200yesPage size actually applied.
pagination.offsetinteger, 0 to 100000yesZero-based row offset actually applied.
pagination.totalinteger, at least 0yesTotal matching resources.
pagination.hasMorebooleanyesTrue when another page is available.

Errors

The shared codes only; see error codes.

List engagement workpapers

GET /api/v1/engagements/{engagement_id}/workpapers

List promoted metadata only; JSONB content and account IDs stay private.

Scope: workpapers:read.

Request

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

ENGAGEMENT_ID = "<engagement-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/engagements/{ENGAGEMENT_ID}/workpapers",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
    params={
        "limit": "50",
    },
)
response.raise_for_status()
print(response.json())
const ENGAGEMENT_ID = "<engagement-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const url = new URL(`https://api.filemark.ca/api/v1/engagements/${ENGAGEMENT_ID}/workpapers`);
url.searchParams.set("limit", "50");

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());

Parameters

ParameterInTypeRequiredDescription
engagement_idpathstring (uuid)yes
limitqueryinteger, 1 to 200, default 50noPage size (1-200).
offsetqueryinteger, 0 to 100000, default 0noZero-based row offset (maximum 100,000).

Response

200. One page of workpaper metadata without payloads.

{
  "data": [
    {
      "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "templateId": "<string>",
      "kind": "<string>",
      "origin": "<string>",
      "status": "<string>",
      "parseStatus": "<string>",
      "tieOutMode": "<string>",
      "tieOutStatus": "<string>",
      "detectedType": "<string>",
      "category": "<string>",
      "version": 1,
      "isReviewed": false,
      "reviewedAt": "2026-07-14T12:00:00Z",
      "sourceFileName": "<string>",
      "linkedAccountCount": 0,
      "createdAt": "2026-07-14T12:00:00Z",
      "updatedAt": "2026-07-14T12:00:00Z"
    }
  ],
  "pagination": {
    "limit": 1,
    "offset": 0,
    "total": 0,
    "hasMore": false
  }
}

Response fields

FieldTypeAlways presentDescription
dataarray of objectsyes
data[].idstring (uuid)yes
data[].templateIdnullable stringno
data[].kindstringyes
data[].originstringyes
data[].statusstringyes
data[].parseStatusnullable stringno
data[].tieOutModenullable stringno
data[].tieOutStatusnullable stringno
data[].detectedTypenullable stringno
data[].categorynullable stringno
data[].versioninteger, at least 1yes
data[].isReviewedbooleanyes
data[].reviewedAtnullable string (date-time)no
data[].sourceFileNamenullable string, up to 512 charactersno
data[].linkedAccountCountinteger, at least 0yes
data[].createdAtstring (date-time)yes
data[].updatedAtstring (date-time)yes
paginationobjectyesBounded offset-pagination metadata.
pagination.limitinteger, 1 to 200yesPage size actually applied.
pagination.offsetinteger, 0 to 100000yesZero-based row offset actually applied.
pagination.totalinteger, at least 0yesTotal matching resources.
pagination.hasMorebooleanyesTrue when another page is available.

Errors

The shared codes only; see error codes.

Get engagement review summary

GET /api/v1/engagements/{engagement_id}/review-summary

Expose safe review counts without inventing a persisted readiness pass.

Scope: review:read.

Request

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

ENGAGEMENT_ID = "<engagement-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/engagements/{ENGAGEMENT_ID}/review-summary",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
)
response.raise_for_status()
print(response.json())
const ENGAGEMENT_ID = "<engagement-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const response = await fetch(`https://api.filemark.ca/api/v1/engagements/${ENGAGEMENT_ID}/review-summary`, {
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Parameters

ParameterInTypeRequiredDescription
engagement_idpathstring (uuid)yes

Response

200. Persisted review indicators, explicitly not an authoritative filing-readiness verdict.

{
  "engagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
  "engagementStatus": "<in_progress | review | complete>",
  "lifecycleStatus": "<open | signed | filed>",
  "signoffs": {
    "preparerSigned": false,
    "reviewerSigned": false,
    "reviewerStatus": "<pending | signed | skipped>",
    "partnerSigned": false
  },
  "workpapers": {
    "total": 0,
    "reviewed": 0,
    "tieOutMatched": 0,
    "tieOutDifference": 0,
    "tieOutIncomplete": 0,
    "tieOutPending": 0
  },
  "accountReviewStatuses": {
    "followUp": 0,
    "analyzed": 0,
    "firstReview": 0,
    "secondReview": 0
  },
  "activeReviewMarks": {
    "total": 0,
    "questions": 0,
    "corrections": 0,
    "firstReview": 0,
    "partnerReview": 0
  },
  "acknowledgedWarningCount": 0,
  "readiness": {
    "evaluated": false,
    "ready": null
  }
}

Response fields

FieldTypeAlways presentDescription
engagementIdstring (uuid)yes
engagementStatusone of in_progress, review, completeyes
lifecycleStatusone of open, signed, filedyes
signoffsobjectyes
signoffs.preparerSignedbooleanyes
signoffs.reviewerSignedbooleanyes
signoffs.reviewerStatusone of pending, signed, skippedyes
signoffs.partnerSignedbooleanyes
workpapersobjectyes
workpapers.totalinteger, at least 0yes
workpapers.reviewedinteger, at least 0yes
workpapers.tieOutMatchedinteger, at least 0yes
workpapers.tieOutDifferenceinteger, at least 0yes
workpapers.tieOutIncompleteinteger, at least 0yes
workpapers.tieOutPendinginteger, at least 0yes
accountReviewStatusesobjectyes
accountReviewStatuses.followUpinteger, at least 0yes
accountReviewStatuses.analyzedinteger, at least 0yes
accountReviewStatuses.firstReviewinteger, at least 0yes
accountReviewStatuses.secondReviewinteger, at least 0yes
activeReviewMarksobjectyes
activeReviewMarks.totalinteger, at least 0yes
activeReviewMarks.questionsinteger, at least 0yes
activeReviewMarks.correctionsinteger, at least 0yes
activeReviewMarks.firstReviewinteger, at least 0yes
activeReviewMarks.partnerReviewinteger, at least 0yes
acknowledgedWarningCountinteger, at least 0yes
readinessobjectyesReadiness state when no authoritative result is persisted.
readiness.evaluatedboolean, always falseno
readiness.readynullno

Errors

The shared codes only; see error codes.

Get an engagement form catalog

GET /api/v1/engagements/{engagement_id}/forms

Lists production form targets whose declared tax-year support window contains the requested engagement. This does not determine filing requirements, resolve a historical form revision, inspect saved form state, compute results, or evaluate readiness.

Scope: engagements:read.

Request

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

ENGAGEMENT_ID = "<engagement-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/engagements/{ENGAGEMENT_ID}/forms",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
)
response.raise_for_status()
print(response.json())
const ENGAGEMENT_ID = "<engagement-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const response = await fetch(`https://api.filemark.ca/api/v1/engagements/${ENGAGEMENT_ID}/forms`, {
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Parameters

ParameterInTypeRequiredDescription
engagement_idpathstring (uuid)yes

Response

200. Bounded year-support catalog for one organization-owned engagement.

{
  "context": {
    "engagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "yearEnd": "2025-12-31",
    "taxYear": 1900,
    "revisionNumber": 1,
    "source": "<prepared | imported>",
    "filedAt": "2026-07-14T12:00:00Z",
    "referenceOnly": false
  },
  "data": [
    {
      "targetId": "<string>",
      "displayName": "<string>",
      "formId": "<string>",
      "taxYearWindow": {
        "from": 1900,
        "through": 1900
      },
      "availability": "supported",
      "applicabilityBasis": "tax_year_window",
      "filingRequirement": "not_evaluated"
    }
  ],
  "evaluation": {
    "formRevisionResolved": false,
    "savedStateEvaluated": false,
    "computationEvaluated": false,
    "readinessEvaluated": false
  }
}

Response fields

FieldTypeAlways presentDescription
contextobjectyesSafe engagement context pinned to the exact requested revision.
context.engagementIdstring (uuid)yes
context.yearEndstring (date)yes
context.taxYearinteger, 1900 to 9999yes
context.revisionNumberinteger, at least 1yes
context.sourceone of prepared, importedyes
context.filedAtnullable string (date-time)yes
context.referenceOnlybooleanyes
dataarray of objects, up to 200 itemsyes
data[].targetIdstring, matching ^(?:S\d+[A-Z]?|T\d+[A-Z]?)$yes
data[].displayNamestring, 1 to 256 charactersyes
data[].formIdstring, matching ^[A-Z0-9_-]{1,64}$yes
data[].taxYearWindowobjectyesInclusive tax-year support window from the canonical registry.
data[].taxYearWindow.frominteger, 1900 to 9999yes
data[].taxYearWindow.throughnullable integer, 1900 to 9999yes
data[].availabilitystring, always "supported"yes
data[].applicabilityBasisstring, always "tax_year_window"yes
data[].filingRequirementstring, always "not_evaluated"yes
evaluationobjectyesPermanent sentinels preventing catalog discovery from implying results.
evaluation.formRevisionResolvedboolean, always falseyes
evaluation.savedStateEvaluatedboolean, always falseyes
evaluation.computationEvaluatedboolean, always falseyes
evaluation.readinessEvaluatedboolean, always falseyes

Errors

Beyond the shared codes in error codes:

  • 503: The canonical form catalog is temporarily unavailable.

Get a saved trial balance

GET /api/v1/engagements/{engagement_id}/trial-balance

Returns a snapshot-bound page of active saved trial-balance accounts and GIFI assignments. Amounts are exact decimal strings in the reported currency and use a debits-positive, credits-negative sign convention. This read does not apply AJEs or tax adjustments and does not evaluate classifications, computations, lineage, or readiness.

Scope: tax-data:read.

Request

curl --get https://api.filemark.ca/api/v1/engagements/$ENGAGEMENT_ID/trial-balance \
  --header "Authorization: Bearer $FILEMARK_ACCESS_TOKEN" \
  --data-urlencode "limit=50"
import os
import requests

ENGAGEMENT_ID = "<engagement-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/engagements/{ENGAGEMENT_ID}/trial-balance",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
    params={
        "limit": "50",
    },
)
response.raise_for_status()
print(response.json())
const ENGAGEMENT_ID = "<engagement-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const url = new URL(`https://api.filemark.ca/api/v1/engagements/${ENGAGEMENT_ID}/trial-balance`);
url.searchParams.set("limit", "50");

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());

Parameters

ParameterInTypeRequiredDescription
engagement_idpathstring (uuid)yes
limitqueryinteger, 1 to 200, default 50noMaximum active accounts to return (1-200).
cursorquerynullable string, 1 to 4096 charactersnoOpaque snapshot-bound cursor from the preceding page.

Response

200. A snapshot-bound page of the requested engagement's saved TB.

{
  "context": {
    "engagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "yearEnd": "2025-12-31",
    "revisionNumber": 1,
    "status": "<in_progress | review | complete>",
    "source": "<prepared | imported>",
    "filedAt": "2026-07-14T12:00:00Z",
    "referenceOnly": false,
    "reportingCurrency": "<string>",
    "currencyBasis": "<canadian_currency | functional_currency | reversionary>",
    "balanceConvention": "debits_positive_credits_negative"
  },
  "sourceRevision": {
    "classifiedReportVersion": 0,
    "gifiAssignmentsVersion": 0,
    "lastModifiedAt": "2026-07-14T12:00:00Z",
    "snapshotDigest": "<string>"
  },
  "availability": "<available | empty | not_imported>",
  "projection": {
    "savedBookBalancesIncluded": true,
    "gifiAssignmentsIncluded": true,
    "archivedAccountsIncluded": false,
    "postedBookAdjustmentsIncluded": false,
    "taxAdjustmentsIncluded": false,
    "classificationIncluded": false,
    "computationEvaluated": false,
    "lineageIncluded": false,
    "readinessEvaluated": false
  },
  "totalStoredAccountCount": 0,
  "archivedAccountCount": 0,
  "data": [
    {
      "id": "<string>",
      "accountCode": "<string>",
      "accountName": "<string>",
      "currentYearBalance": "125000.5",
      "priorYearBalance": "-4200",
      "gifiCode": "<string>",
      "changeStatus": "<new | removed | significant_increase | significant_decrease | minor_change | unchanged | unknown>"
    }
  ],
  "pagination": {
    "limit": 1,
    "total": 0,
    "nextCursor": "<string>",
    "hasMore": false
  }
}

Response fields

FieldTypeAlways presentDescription
contextobjectyes
context.engagementIdstring (uuid)yes
context.yearEndstring (date)yes
context.revisionNumberinteger, at least 1yes
context.statusone of in_progress, review, completeyes
context.sourceone of prepared, importedyes
context.filedAtnullable string (date-time)yes
context.referenceOnlybooleanyes
context.reportingCurrencystring, matching ^[A-Z]{3}$yes
context.currencyBasisone of canadian_currency, functional_currency, reversionaryyes
context.balanceConventionstring, always "debits_positive_credits_negative"yes
sourceRevisionobjectyesVersion vector and content address for the exact saved projection.
sourceRevision.classifiedReportVersioninteger, at least 0yes
sourceRevision.gifiAssignmentsVersioninteger, at least 0yes
sourceRevision.lastModifiedAtstring (date-time)yes
sourceRevision.snapshotDigeststring, matching ^sha256:[0-9a-f]{64}$yes
availabilityone of available, empty, not_importedyes
projectionobjectyesSemantic sentinels that prevent consumers from assuming extra state.
projection.savedBookBalancesIncludedboolean, always trueyes
projection.gifiAssignmentsIncludedboolean, always trueyes
projection.archivedAccountsIncludedboolean, always falseyes
projection.postedBookAdjustmentsIncludedboolean, always falseyes
projection.taxAdjustmentsIncludedboolean, always falseyes
projection.classificationIncludedboolean, always falseyes
projection.computationEvaluatedboolean, always falseyes
projection.lineageIncludedboolean, always falseyes
projection.readinessEvaluatedboolean, always falseyes
totalStoredAccountCountinteger, at least 0yes
archivedAccountCountinteger, at least 0yes
dataarray of objects, up to 200 itemsyes
data[].idstring, 1 to 128 charactersyes
data[].accountCodenullable string, up to 128 charactersyes
data[].accountNamestring, up to 512 charactersyes
data[].currentYearBalancedecimal string, 1 to 96 charactersyesExact base-10 amount in the engagement reporting currency.
data[].priorYearBalancenullable decimal string, 1 to 96 charactersyes
data[].gifiCodenullable string, matching ^[0-9]{4}$yes
data[].changeStatusone of new, removed, significant_increase, significant_decrease, minor_change, unchanged, unknownyes
paginationobjectyes
pagination.limitinteger, 1 to 200yes
pagination.totalinteger, at least 0yes
pagination.nextCursornullable stringyes
pagination.hasMorebooleanyes

Errors

Beyond the shared codes in error codes:

  • 400: The pagination cursor is malformed or invalid.
  • 404: The engagement does not exist in the caller's organization.
  • 409: The saved trial balance is inconsistent or changed between pages.

Get a saved engagement account

GET /api/v1/engagements/{engagement_id}/accounts/{account_id}

Returns one active saved trial-balance account with an allowlisted classification, accepted GIFI mapping provenance, current chart-of-accounts metadata, and a bounded adjustment summary. Book AJEs are re-evaluated before posting. Workpaper tax amounts are counted as saved sources only and are never allocated or totalled per account.

Scope: tax-data:read.

Request

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

ENGAGEMENT_ID = "<engagement-id>"
ACCOUNT_ID = "<account-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/engagements/{ENGAGEMENT_ID}/accounts/{ACCOUNT_ID}",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
)
response.raise_for_status()
print(response.json())
const ENGAGEMENT_ID = "<engagement-id>";
const ACCOUNT_ID = "<account-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const response = await fetch(`https://api.filemark.ca/api/v1/engagements/${ENGAGEMENT_ID}/accounts/${ACCOUNT_ID}`, {
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Parameters

ParameterInTypeRequiredDescription
engagement_idpathstring (uuid)yes
account_idpathstring, 1 to 128 charactersyes

Response

200

{
  "context": {
    "engagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "yearEnd": "2025-12-31",
    "revisionNumber": 1,
    "status": "<in_progress | review | complete>",
    "source": "<prepared | imported>",
    "filedAt": "2026-07-14T12:00:00Z",
    "referenceOnly": false,
    "reportingCurrency": "<string>",
    "currencyBasis": "<canadian_currency | functional_currency | reversionary>",
    "balanceConvention": "debits_positive_credits_negative"
  },
  "sourceRevision": {
    "classifiedReportVersion": 0,
    "gifiAssignmentsVersion": 0,
    "gifiCarriedForwardVersion": 0,
    "gifiAutoAppliedAccountIdsVersion": 0,
    "ajeEntriesVersion": 0,
    "lastModifiedAt": "2026-07-14T12:00:00Z",
    "workpaperRevisionDigest": "<string>",
    "snapshotDigest": "<string>"
  },
  "account": {
    "id": "<string>",
    "accountCode": "<string>",
    "accountName": "<string>",
    "currentYearBalance": "125000.5",
    "priorYearBalance": "-4200",
    "changeStatus": "<new | removed | significant_increase | significant_decrease | minor_change | unchanged | unknown>"
  },
  "classification": {
    "availability": "<classified | not_classified>",
    "userStatus": "<pending | modified | accepted>",
    "ruleId": "<string>",
    "source": "<rule | prior_year | llm | llm_failed | manual>",
    "confidence": "<decimal>",
    "assumption": "<string>",
    "bookTreatment": "<accept_as_booked | reclassify | accrue_adjust | write_off | requires_review | unclassified>",
    "taxTreatment": "<fully_deductible | non_deductible_full | partially_deductible | capital_cca | timing_difference | deduct_other_schedule | non_taxable | disclosure_only | informational | unclassified>",
    "bookTreatmentSource": "<derived | manual>",
    "taxTreatmentSource": "<derived | manual>",
    "s1Line": "<string>",
    "feedsSchedule": "<string>",
    "taxAssumptionNote": "<string>",
    "derivationRuleId": "<string>",
    "adjustmentType": "<addition | deduction>",
    "deductibilityRule": "<string>",
    "deductibilityPercentage": "<decimal>",
    "incomeType": "<active_business | property | rental | capital>",
    "incomeTypeSource": "<derived | manual>",
    "foreignSource": false,
    "subtype": "<string>",
    "conditionalOn": "<string>",
    "templateId": "<string>",
    "itaReferences": [
      "<string>"
    ]
  },
  "gifiMapping": {
    "assignedGifiCode": "<string>",
    "carriedForward": false,
    "machineApplied": false,
    "relationToCurrentDefault": "<unassigned | no_default | matches_default | overrides_default>",
    "chartAccount": {
      "id": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "naturalKey": "<string>",
      "accountType": "<asset | liability | equity | revenue | expense | unassigned>",
      "accountSubtype": "<string>",
      "subtypeSource": "<string>",
      "accountTypeSource": "<inferred | firm_template | connector | coa_file | user>",
      "isContra": false,
      "isActive": false,
      "defaultGifiCode": "<string>",
      "defaultGifiSource": "<inferred | firm_template | carried | connector | coa_file | user>",
      "parentAccountCode": "<string>",
      "updatedAt": "2026-07-14T12:00:00Z"
    }
  },
  "adjustmentSummary": {
    "postedBookAdjustmentTotal": "125000.5",
    "adjustedBookBalance": "-4200",
    "postedBookAdjustmentCount": 0,
    "blockedBookAdjustmentCount": 0,
    "workpaperTaxAdjustmentSourceCount": 0,
    "schedule1ImpactEvaluated": false
  },
  "projection": {
    "savedStateOnly": true,
    "classificationIncluded": true,
    "gifiMappingIncluded": true,
    "postedBookAdjustmentsSummarized": true,
    "workpaperTaxAdjustmentsSummarized": true,
    "workpaperAmountsAllocatedToAccount": false,
    "schedule1ImpactEvaluated": false,
    "computationEvaluated": false,
    "lineageIncluded": false,
    "readinessEvaluated": false,
    "storageMetadataIncluded": false
  }
}

Response fields

FieldTypeAlways presentDescription
contextobjectyes
context.engagementIdstring (uuid)yes
context.yearEndstring (date)yes
context.revisionNumberinteger, at least 1yes
context.statusone of in_progress, review, completeyes
context.sourceone of prepared, importedyes
context.filedAtnullable string (date-time)yes
context.referenceOnlybooleanyes
context.reportingCurrencystring, matching ^[A-Z]{3}$yes
context.currencyBasisone of canadian_currency, functional_currency, reversionaryyes
context.balanceConventionstring, always "debits_positive_credits_negative"yes
sourceRevisionobjectyes
sourceRevision.classifiedReportVersioninteger, at least 0yes
sourceRevision.gifiAssignmentsVersioninteger, at least 0yes
sourceRevision.gifiCarriedForwardVersioninteger, at least 0yes
sourceRevision.gifiAutoAppliedAccountIdsVersioninteger, at least 0yes
sourceRevision.ajeEntriesVersioninteger, at least 0yes
sourceRevision.lastModifiedAtstring (date-time)yes
sourceRevision.workpaperRevisionDigeststring, matching ^sha256:[0-9a-f]{64}$yes
sourceRevision.snapshotDigeststring, matching ^sha256:[0-9a-f]{64}$yes
accountobjectyes
account.idstring, 1 to 128 charactersyes
account.accountCodenullable string, up to 128 charactersyes
account.accountNamestring, up to 512 charactersyes
account.currentYearBalancedecimal string, 1 to 96 charactersyesExact base-10 amount in the engagement reporting currency.
account.priorYearBalancenullable decimal string, 1 to 96 charactersyes
account.changeStatusone of new, removed, significant_increase, significant_decrease, minor_change, unchanged, unknownyes
classificationobjectyes
classification.availabilityone of classified, not_classifiedyes
classification.userStatusnullable one of pending, modified, acceptedyes
classification.ruleIdnullable string, up to 256 charactersyes
classification.sourcenullable one of rule, prior_year, llm, llm_failed, manualyes
classification.confidencenullable decimal string, 1 to 96 charactersyes
classification.assumptionnullable string, up to 4000 charactersyes
classification.bookTreatmentnullable one of accept_as_booked, reclassify, accrue_adjust, write_off, requires_review, unclassifiedyes
classification.taxTreatmentnullable one of fully_deductible, non_deductible_full, partially_deductible, capital_cca, timing_difference, deduct_other_schedule, non_taxable, disclosure_only, informational, unclassifiedyes
classification.bookTreatmentSourcenullable one of derived, manualyes
classification.taxTreatmentSourcenullable one of derived, manualyes
classification.s1Linenullable string, up to 32 charactersyes
classification.feedsSchedulenullable string, up to 32 charactersyes
classification.taxAssumptionNotenullable string, up to 4000 charactersyes
classification.derivationRuleIdnullable string, up to 256 charactersyes
classification.adjustmentTypenullable one of addition, deductionyes
classification.deductibilityRulenullable string, up to 2000 charactersyes
classification.deductibilityPercentagenullable decimal string, 1 to 96 charactersyes
classification.incomeTypenullable one of active_business, property, rental, capitalyes
classification.incomeTypeSourcenullable one of derived, manualyes
classification.foreignSourcenullable booleanyes
classification.subtypenullable string, up to 64 charactersyes
classification.conditionalOnnullable string, up to 2000 charactersyes
classification.templateIdnullable string, up to 256 charactersyes
classification.itaReferencesarray of strings, up to 32 itemsyes
gifiMappingobjectyes
gifiMapping.assignedGifiCodenullable string, matching ^[0-9]{4}$yes
gifiMapping.carriedForwardbooleanyes
gifiMapping.machineAppliedbooleanyes
gifiMapping.relationToCurrentDefaultone of unassigned, no_default, matches_default, overrides_defaultyes
gifiMapping.chartAccountnullable objectyes
gifiMapping.chartAccount.idstring (uuid)when chartAccount is set
gifiMapping.chartAccount.naturalKeystring, 1 to 517 characterswhen chartAccount is set
gifiMapping.chartAccount.accountTypeone of asset, liability, equity, revenue, expense, unassignedwhen chartAccount is set
gifiMapping.chartAccount.accountSubtypenullable string, up to 256 characterswhen chartAccount is set
gifiMapping.chartAccount.subtypeSourcenullable string, up to 64 characterswhen chartAccount is set
gifiMapping.chartAccount.accountTypeSourceone of inferred, firm_template, connector, coa_file, userwhen chartAccount is set
gifiMapping.chartAccount.isContrabooleanwhen chartAccount is set
gifiMapping.chartAccount.isActivebooleanwhen chartAccount is set
gifiMapping.chartAccount.defaultGifiCodenullable string, matching ^[0-9]{4}$when chartAccount is set
gifiMapping.chartAccount.defaultGifiSourcenullable one of inferred, firm_template, carried, connector, coa_file, userwhen chartAccount is set
gifiMapping.chartAccount.parentAccountCodenullable string, up to 128 characterswhen chartAccount is set
gifiMapping.chartAccount.updatedAtstring (date-time)when chartAccount is set
adjustmentSummaryobjectyes
adjustmentSummary.postedBookAdjustmentTotaldecimal string, 1 to 96 charactersyesExact base-10 amount in the engagement reporting currency.
adjustmentSummary.adjustedBookBalancedecimal string, 1 to 96 charactersyesExact base-10 amount in the engagement reporting currency.
adjustmentSummary.postedBookAdjustmentCountinteger, at least 0yes
adjustmentSummary.blockedBookAdjustmentCountinteger, at least 0yes
adjustmentSummary.workpaperTaxAdjustmentSourceCountinteger, at least 0yes
adjustmentSummary.schedule1ImpactEvaluatedboolean, always falseyes
projectionobjectyes
projection.savedStateOnlyboolean, always trueyes
projection.classificationIncludedboolean, always trueyes
projection.gifiMappingIncludedboolean, always trueyes
projection.postedBookAdjustmentsSummarizedboolean, always trueyes
projection.workpaperTaxAdjustmentsSummarizedboolean, always trueyes
projection.workpaperAmountsAllocatedToAccountboolean, always falseyes
projection.schedule1ImpactEvaluatedboolean, always falseyes
projection.computationEvaluatedboolean, always falseyes
projection.lineageIncludedboolean, always falseyes
projection.readinessEvaluatedboolean, always falseyes
projection.storageMetadataIncludedboolean, always falseyes

Errors

Beyond the shared codes in error codes:

  • 404: The engagement or active account does not exist in the caller's organization.
  • 409: The saved account data cannot be represented safely.

List saved account adjustments

GET /api/v1/engagements/{engagement_id}/accounts/{account_id}/adjustments

Returns posted or blocked book AJEs affecting the requested account and separately lists linked workpaper tax-adjustment sources. Only requested-account AJE lines are exposed. A shared workpaper amount is the whole workpaper amount, not an allocation to this account, and Schedule 1 routing is not evaluated by this saved-state read.

Scope: tax-data:read.

Request

curl https://api.filemark.ca/api/v1/engagements/$ENGAGEMENT_ID/accounts/$ACCOUNT_ID/adjustments \
  --header "Authorization: Bearer $FILEMARK_ACCESS_TOKEN"
import os
import requests

ENGAGEMENT_ID = "<engagement-id>"
ACCOUNT_ID = "<account-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.get(
    f"https://api.filemark.ca/api/v1/engagements/{ENGAGEMENT_ID}/accounts/{ACCOUNT_ID}/adjustments",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
)
response.raise_for_status()
print(response.json())
const ENGAGEMENT_ID = "<engagement-id>";
const ACCOUNT_ID = "<account-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const response = await fetch(`https://api.filemark.ca/api/v1/engagements/${ENGAGEMENT_ID}/accounts/${ACCOUNT_ID}/adjustments`, {
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Parameters

ParameterInTypeRequiredDescription
engagement_idpathstring (uuid)yes
account_idpathstring, 1 to 128 charactersyes

Response

200

{
  "context": {
    "engagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "yearEnd": "2025-12-31",
    "revisionNumber": 1,
    "status": "<in_progress | review | complete>",
    "source": "<prepared | imported>",
    "filedAt": "2026-07-14T12:00:00Z",
    "referenceOnly": false,
    "reportingCurrency": "<string>",
    "currencyBasis": "<canadian_currency | functional_currency | reversionary>",
    "balanceConvention": "debits_positive_credits_negative"
  },
  "sourceRevision": {
    "classifiedReportVersion": 0,
    "gifiAssignmentsVersion": 0,
    "gifiCarriedForwardVersion": 0,
    "gifiAutoAppliedAccountIdsVersion": 0,
    "ajeEntriesVersion": 0,
    "lastModifiedAt": "2026-07-14T12:00:00Z",
    "workpaperRevisionDigest": "<string>",
    "snapshotDigest": "<string>"
  },
  "account": {
    "id": "<string>",
    "accountCode": "<string>",
    "accountName": "<string>",
    "currentYearBalance": "125000.5",
    "priorYearBalance": "-4200",
    "changeStatus": "<new | removed | significant_increase | significant_decrease | minor_change | unchanged | unknown>"
  },
  "projection": {
    "postedBookAdjustmentsIncluded": true,
    "blockedBookAdjustmentsIncluded": true,
    "workpaperTaxAdjustmentSourcesIncluded": true,
    "unrelatedBookAdjustmentLinesIncluded": false,
    "workpaperAmountsAllocatedToAccount": false,
    "schedule1ImpactEvaluated": false,
    "computationEvaluated": false,
    "readinessEvaluated": false,
    "storageMetadataIncluded": false
  },
  "postedBookAdjustmentTotal": "125000.5",
  "adjustedBookBalance": "-4200",
  "bookAdjustments": [
    {
      "kind": "book_aje",
      "id": "<string>",
      "number": 1,
      "name": "<string>",
      "description": "<string>",
      "entryType": "<adjusting | reclassifying | tax_provision | potential>",
      "source": "<preparer | client>",
      "entryDate": "2025-12-31",
      "recurring": false,
      "postingStatus": "<posted | blocked | excluded>",
      "blockReason": "<unbalanced | unlinked_account>",
      "totalDebits": "125000.5",
      "totalCredits": "-4200",
      "accountEffect": "0",
      "requestedAccountLines": [
        {
          "id": "<string>",
          "type": "<debit | credit>",
          "accountId": "<string>",
          "accountCode": "<string>",
          "accountName": "<string>",
          "amount": "125000.5"
        }
      ]
    }
  ],
  "workpaperTaxAdjustments": [
    {
      "kind": "workpaper_tax_adjustment",
      "workpaperId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
      "templateId": "<string>",
      "displayName": "<string>",
      "version": 1,
      "lifecycleStatus": "<string>",
      "tieOutStatus": "<matched | difference | pending | incomplete>",
      "adjustmentAmount": "125000.5",
      "adjustmentType": "<addition | deduction>",
      "adjustmentStatus": "<string>",
      "legacyStatusDefaulted": false,
      "requiresManualReview": false,
      "linkedAccountCount": 1,
      "linkedAccountIds": [
        "<string>"
      ],
      "allocationBasis": "workpaper_total_not_account_allocated",
      "schedule1ImpactEvaluated": false
    }
  ]
}

Response fields

FieldTypeAlways presentDescription
contextobjectyes
context.engagementIdstring (uuid)yes
context.yearEndstring (date)yes
context.revisionNumberinteger, at least 1yes
context.statusone of in_progress, review, completeyes
context.sourceone of prepared, importedyes
context.filedAtnullable string (date-time)yes
context.referenceOnlybooleanyes
context.reportingCurrencystring, matching ^[A-Z]{3}$yes
context.currencyBasisone of canadian_currency, functional_currency, reversionaryyes
context.balanceConventionstring, always "debits_positive_credits_negative"yes
sourceRevisionobjectyes
sourceRevision.classifiedReportVersioninteger, at least 0yes
sourceRevision.gifiAssignmentsVersioninteger, at least 0yes
sourceRevision.gifiCarriedForwardVersioninteger, at least 0yes
sourceRevision.gifiAutoAppliedAccountIdsVersioninteger, at least 0yes
sourceRevision.ajeEntriesVersioninteger, at least 0yes
sourceRevision.lastModifiedAtstring (date-time)yes
sourceRevision.workpaperRevisionDigeststring, matching ^sha256:[0-9a-f]{64}$yes
sourceRevision.snapshotDigeststring, matching ^sha256:[0-9a-f]{64}$yes
accountobjectyes
account.idstring, 1 to 128 charactersyes
account.accountCodenullable string, up to 128 charactersyes
account.accountNamestring, up to 512 charactersyes
account.currentYearBalancedecimal string, 1 to 96 charactersyesExact base-10 amount in the engagement reporting currency.
account.priorYearBalancenullable decimal string, 1 to 96 charactersyes
account.changeStatusone of new, removed, significant_increase, significant_decrease, minor_change, unchanged, unknownyes
projectionobjectyes
projection.postedBookAdjustmentsIncludedboolean, always trueyes
projection.blockedBookAdjustmentsIncludedboolean, always trueyes
projection.workpaperTaxAdjustmentSourcesIncludedboolean, always trueyes
projection.unrelatedBookAdjustmentLinesIncludedboolean, always falseyes
projection.workpaperAmountsAllocatedToAccountboolean, always falseyes
projection.schedule1ImpactEvaluatedboolean, always falseyes
projection.computationEvaluatedboolean, always falseyes
projection.readinessEvaluatedboolean, always falseyes
projection.storageMetadataIncludedboolean, always falseyes
postedBookAdjustmentTotaldecimal string, 1 to 96 charactersyesExact base-10 amount in the engagement reporting currency.
adjustedBookBalancedecimal string, 1 to 96 charactersyesExact base-10 amount in the engagement reporting currency.
bookAdjustmentsarray of objects, up to 5000 itemsyes
bookAdjustments[].kindstring, always "book_aje"yes
bookAdjustments[].idstring, 1 to 128 charactersyes
bookAdjustments[].numberinteger, at least 1yes
bookAdjustments[].namestring, up to 512 charactersyes
bookAdjustments[].descriptionstring, up to 4000 charactersyes
bookAdjustments[].entryTypeone of adjusting, reclassifying, tax_provision, potentialyes
bookAdjustments[].sourceone of preparer, clientyes
bookAdjustments[].entryDatenullable string (date)yes
bookAdjustments[].recurringbooleanyes
bookAdjustments[].postingStatusone of posted, blocked, excludedyes
bookAdjustments[].blockReasonnullable one of unbalanced, unlinked_accountyes
bookAdjustments[].totalDebitsdecimal string, 1 to 96 charactersyesExact base-10 amount in the engagement reporting currency.
bookAdjustments[].totalCreditsdecimal string, 1 to 96 charactersyesExact base-10 amount in the engagement reporting currency.
bookAdjustments[].accountEffectnullable decimal string, 1 to 96 charactersyes
bookAdjustments[].requestedAccountLinesarray of objects, up to 2000 itemsyes
bookAdjustments[].requestedAccountLines[].idstring, 1 to 128 charactersyes
bookAdjustments[].requestedAccountLines[].typeone of debit, credityes
bookAdjustments[].requestedAccountLines[].accountIdstring, 1 to 128 charactersyes
bookAdjustments[].requestedAccountLines[].accountCodenullable string, up to 128 charactersyes
bookAdjustments[].requestedAccountLines[].accountNamestring, up to 512 charactersyes
bookAdjustments[].requestedAccountLines[].amountdecimal string, 1 to 96 charactersyesExact base-10 amount in the engagement reporting currency.
workpaperTaxAdjustmentsarray of objects, up to 2000 itemsyes
workpaperTaxAdjustments[].kindstring, always "workpaper_tax_adjustment"yes
workpaperTaxAdjustments[].workpaperIdstring (uuid)yes
workpaperTaxAdjustments[].templateIdnullable string, up to 256 charactersyes
workpaperTaxAdjustments[].displayNamenullable string, up to 512 charactersyes
workpaperTaxAdjustments[].versioninteger, at least 1yes
workpaperTaxAdjustments[].lifecycleStatusstring, 1 to 64 charactersyes
workpaperTaxAdjustments[].tieOutStatusnullable one of matched, difference, pending, incompleteyes
workpaperTaxAdjustments[].adjustmentAmountnullable decimal string, 1 to 96 charactersyes
workpaperTaxAdjustments[].adjustmentTypenullable one of addition, deductionyes
workpaperTaxAdjustments[].adjustmentStatusstring, 1 to 128 charactersyes
workpaperTaxAdjustments[].legacyStatusDefaultedbooleanyes
workpaperTaxAdjustments[].requiresManualReviewbooleanyes
workpaperTaxAdjustments[].linkedAccountCountinteger, at least 1yes
workpaperTaxAdjustments[].linkedAccountIdsarray of strings, 1 to 20000 itemsyes
workpaperTaxAdjustments[].allocationBasisstring, always "workpaper_total_not_account_allocated"yes
workpaperTaxAdjustments[].schedule1ImpactEvaluatedboolean, always falseyes

Errors

Beyond the shared codes in error codes:

  • 404: The engagement or active account does not exist in the caller's organization.
  • 409: The saved account data cannot be represented safely.

Compute an engagement's saved state with cells replaced

POST /api/v1/engagements/{engagement_id}/computations/scenario

Runs the requested computation targets against the engagement's own saved inputs, replacing only the cells this request names. Cells the request omits keep their saved values, so a what-if holds everything else equal without the caller reassembling the engagement's facts. The saved inputs are never returned; the response carries the computed results and the lineage hash of the state they came from, so two responses are comparable exactly when their hashes match. Nothing is persisted, and readiness is not evaluated: this is engine output, not a filing verdict.

Scopes: tax-data:read + tax:compute.

Request

curl --request POST https://api.filemark.ca/api/v1/engagements/$ENGAGEMENT_ID/computations/scenario \
  --header "Authorization: Bearer $FILEMARK_ACCESS_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "compute": [
      "part_i_tax"
    ],
    "inputs": {
      "isCCPC": true
    }
  }'
import os
import requests

ENGAGEMENT_ID = "<engagement-id>"
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.post(
    f"https://api.filemark.ca/api/v1/engagements/{ENGAGEMENT_ID}/computations/scenario",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
    json={
        "compute": [
            "part_i_tax",
        ],
        "inputs": {
            "isCCPC": True,
        },
    },
)
response.raise_for_status()
print(response.json())
const ENGAGEMENT_ID = "<engagement-id>";
const FILEMARK_ACCESS_TOKEN = process.env.FILEMARK_ACCESS_TOKEN;

const response = await fetch(`https://api.filemark.ca/api/v1/engagements/${ENGAGEMENT_ID}/computations/scenario`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "compute": [
      "part_i_tax"
    ],
    "inputs": {
      "isCCPC": true
    }
  }),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Parameters

ParameterInTypeRequiredDescription
engagement_idpathstring (uuid)yes

Request body

Targets to compute from an engagement's saved data, named cells replaced.

FieldTypeRequiredDescription
computearray of strings, 1 to 100 itemsyesSchedule/result keys to compute; dependencies run automatically.
inputsobjectnoInput cells to replace on the engagement's saved computation body; every cell the request omits keeps its saved value. A member replaces its whole top-level cell rather than merging into it, and explicit null is the unanswered-fact sentinel rather than a deletion. Membership and JSON type are checked against the same published cells the batch boundary admits. The cells that identify the engagement's taxation period and its server-authored filing lineage cannot be replaced.
inputs.*anynoMembers not listed here.

Response

200. Versioned saved-engagement computation shared by REST and MCP.

{
  "data": {
    "engagementId": "3f1a5b2c-9d4e-4f8a-b1c2-0a1b2c3d4e5f",
    "sourceStateSha256": "<string>",
    "appliedOverrides": [
      "<string>"
    ],
    "results": {
      "<member>": "<any>"
    }
  },
  "computeVersion": "<string>",
  "engineSchemaVersion": "<string>",
  "ratesVersion": "<string>",
  "timestamp": "2026-07-14T12:00:00Z"
}

Response fields

FieldTypeAlways presentDescription
dataobjectyesOne deterministic computation over an engagement's saved inputs.
data.engagementIdstring (uuid)yes
data.sourceStateSha256stringyesLineage hash of the engagement's saved state this computation was built from. Two responses carrying the same hash were computed from the same saved facts and are comparable; a different hash means the engagement changed in between.
data.appliedOverridesarray of stringsyesThe input cells this request replaced, in sorted order. Every other cell came from the engagement's saved inputs.
data.resultsobjectyesEngine output for the requested targets and their automatic dependencies. It is a computation, not a filing verdict: readiness is not evaluated here.
data.results.*anynoThe target's output cells; see the computation reference.
computeVersionstringyes
engineSchemaVersionstringyes
ratesVersionstringyes
timestampstring (date-time)yes

Errors

Beyond the shared codes in error codes:

  • 404: The engagement does not exist in the caller's organization.
  • 409: The saved engagement state cannot be computed.

List computation targets

GET /api/v1/computations

Scope: tax:compute.

Request

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());

Response

200

{
  "data": {
    "batchTargets": [
      "<string>"
    ],
    "batchDependencies": {
      "<key>": [
        "<string>"
      ]
    },
    "rolloverTargets": [
      "<string>"
    ]
  }
}

Response fields

FieldTypeAlways presentDescription
dataobjectyes
data.batchTargetsarray of stringsyes
data.batchDependenciesmap of array of stringsyes
data.batchDependencies.{key}array of stringsper key
data.rolloverTargetsarray of stringsyes

Errors

The shared codes only; see error codes.

Get a computation target contract

GET /api/v1/computations/targets/{target_id}

Returns every input cell one computation target accepts and every output cell its result carries, with JSON types, the exact payloadContract selector, and the target's executed example request. The input cells are the same published dictionary the computation boundary admits against, so a cell listed here is a cell POST /api/v1/computations/batch accepts. Cell values stay unvalidated without a payloadContract.

Scope: tax:compute.

Request

curl https://api.filemark.ca/api/v1/computations/targets/part_i_tax \
  --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/targets/part_i_tax",
    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/targets/part_i_tax", {
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Parameters

ParameterInTypeRequiredDescription
target_idpathstring, 1 to 64 characters, matching ^[a-z][a-z0-9_-]*$yesBatch or rollover target id from the computation catalog.

Response

200. One target's published contract, shared by REST and MCP.

{
  "data": {
    "id": "<string>",
    "kind": "<batch | rollover>",
    "program": "<string>",
    "jurisdiction": "<string>",
    "status": "<string>",
    "supportedTaxYears": [
      {
        "first": 0,
        "last": 0
      }
    ],
    "contract": {
      "boundaryProfileId": "<string>",
      "payloadSchemaVersion": "<string>"
    },
    "inputs": [
      {
        "path": "<string>",
        "types": [
          "<string>"
        ],
        "required": false,
        "requiredOnDefaultBoundary": false,
        "strictPinned": false,
        "<output cell>": "<any>"
      }
    ],
    "outputs": [
      {
        "path": "<string>",
        "types": [
          "<string>"
        ],
        "<output cell>": "<any>"
      }
    ],
    "exampleInput": {
      "<member>": "<any>"
    },
    "dependencies": [
      "<string>"
    ]
  }
}

Response fields

FieldTypeAlways presentDescription
dataobjectyesThe cells one computation target accepts and returns.
data.idstringyes
data.kindone of batch, rolloveryes
data.programnullable stringno
data.jurisdictionnullable stringno
data.statusnullable stringnoContract lifecycle status of the target profile. It is not a filing, CRA-acceptance, or tax-semantics determination.
data.supportedTaxYearsnullable array of objectsnoInclusive taxation-year windows for schedule targets; null where a year window does not apply, as for rollover targets.
data.supportedTaxYears[].firstintegerwhen supportedTaxYears is set
data.supportedTaxYears[].lastnullable integerwhen supportedTaxYears is setLast supported taxation year; null means open-ended.
data.contractnullable objectnoThe exact selector to send as payloadContract to validate a request against this target's pinned schema pair.
data.contract.boundaryProfileIdstring, 1 to 128 characters, matching ^[a-z][a-z0-9_.-]*$when contract is setExact strict computation boundary profile identifier.
data.contract.payloadSchemaVersionstring, up to 64 characters, matching ^[0-9]+\.[0-9]+\.[0-9]+$when contract is setExact semantic version of the target payload schema pair.
data.inputsarray of objectsyes
data.inputs[].pathstringyesDotted path of this cell inside the request's inputs object; a [] segment addresses the elements of an array.
data.inputs[].typesarray of stringsyesEvery JSON type the boundary admits at this position.
data.inputs[].requiredbooleanyesWhether the strict payload contract requires this cell. On the default boundary only the cells flagged requiredOnDefaultBoundary are required.
data.inputs[].requiredOnDefaultBoundarybooleanyesWhether every request needs this cell: the default boundary (no payloadContract) refuses the request when it is omitted or null. True for a batch target's taxYear and for the statutory scope facts a rollover cannot answer on the caller's behalf.
data.inputs[].strictPinnedbooleanyesWhether the strict profile admits exactly one value here. A pinned cell constrains only a request that names a payloadContract; the default boundary leaves values free.
data.inputs[].*anynoMembers not listed here.
data.outputsarray of objectsyes
data.outputs[].pathstringyesDotted path of this cell inside the target's result object; a [] segment addresses the elements of an array.
data.outputs[].typesarray of stringsyesEvery JSON type this result position can carry.
data.outputs[].*anynoMembers not listed here.
data.exampleInputnullable objectnoThe target's executed, admission-checked golden request body: the value a caller sends as inputs.
data.exampleInput.*anynoMembers not listed here.
data.dependenciesnullable array of stringsnoBatch targets that run automatically with this one, whose input cells the request may therefore also carry. Null for rollovers.

Errors

Beyond the shared codes in error codes:

  • 404: The computation target is not in the public catalog.

Compute tax schedules

POST /api/v1/computations/batch

Scope: tax:compute.

Request

curl --request POST https://api.filemark.ca/api/v1/computations/batch \
  --header "Authorization: Bearer $FILEMARK_ACCESS_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "compute": [
      "part_i_tax"
    ],
    "inputs": {
      "schedule1": {},
      "taxYear": 2025,
      "fiscalStart": "2025-01-01",
      "fiscalEnd": "2025-12-31",
      "isCCPC": true,
      "daysInYear": 365
    }
  }'
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": [
            "part_i_tax",
        ],
        "inputs": {
            "schedule1": {},
            "taxYear": 2025,
            "fiscalStart": "2025-01-01",
            "fiscalEnd": "2025-12-31",
            "isCCPC": True,
            "daysInYear": 365,
        },
    },
)
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": [
      "part_i_tax"
    ],
    "inputs": {
      "schedule1": {},
      "taxYear": 2025,
      "fiscalStart": "2025-01-01",
      "fiscalEnd": "2025-12-31",
      "isCCPC": true,
      "daysInYear": 365
    }
  }),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Request body

A bounded set of schedule targets plus their canonical engine inputs.

FieldTypeRequiredDescription
computearray of strings, 1 to 100 itemsyesSchedule/result keys to compute; dependencies run automatically.
inputsobjectnoCanonical batch-engine inputs. Every member must be a published input cell of a requested target or of a dependency that runs automatically, with the published JSON type; unpublished members and wrong-typed cells are rejected with per-field details. Cell values beyond their JSON type are validated only under a payloadContract selector.
inputs.*anynoMembers not listed here.
vendorInputobjectnoOptional vendor-cell input adapter. Each cell must resolve unambiguously through the versioned handoff mapping to an approved one-to-one canonical input path. Omit for canonical inputs only; null is not valid.
vendorInput.vendorone of taxcycle, taxprepwhen vendorInput is setVendor vocabulary used by every key in cells.
vendorInput.cellsobjectwhen vendorInput is setExact, case-sensitive TaxCycle field codes or Taxprep cell IDs. Values retain their canonical Filemark JSON types and are never decoded, signed, rounded, or otherwise coerced.
vendorInput.cells.*anynoMembers not listed here.
payloadContractobjectnoOptional exact strict target contract. Omit this property to use the published legacy computation boundary; null is not valid.
payloadContract.boundaryProfileIdstring, 1 to 128 characters, matching ^[a-z][a-z0-9_.-]*$when payloadContract is setExact strict computation boundary profile identifier.
payloadContract.payloadSchemaVersionstring, up to 64 characters, matching ^[0-9]+\.[0-9]+\.[0-9]+$when payloadContract is setExact semantic version of the target payload schema pair.
handoffobjectnoOptional handoff projection. Formats 'json' and 'file' carry the selected vendor's import identifiers and encoded schedule values, byte-identical to the Filemark companion files, or as those files themselves, plus coverage warnings and mapping provenance. Format 'gfi' takes no vendor and returns the universal RC4088 file from computed Schedule 100/125 amounts; corporationName and businessNumber are required for that format. T2-jacket and S141 vendor-cell rows are out of stateless scope. A safety gate that would block a companion-file export returns data.handoff.blocked with the reason while data.results stays intact. Verify cell identifiers: the build they were mapped against is reported as data.handoff.vendorEdition, confirm your install matches it before importing. Omit this property for no projection; null is not valid.
handoff.vendorone of taxcycle, taxprep, ifirmwhen handoff is setReceiving product whose import identifiers the response's data.handoff block carries: 'taxcycle' (per-form Excel Import Forms field codes), 'taxprep' (Corporate Taxprep .csv cell IDs), or 'ifirm' (CCH iFirm cells/setdata cell paths). Required for formats 'json' and 'file'; omit it for format 'gfi'.
handoff.formatone of json, file, gfiwhen handoff is setContainer for those cells. 'json' (the default) returns them as structured data: data.handoff.cells, or data.handoff.forms for TaxCycle. 'file' returns the receiving product's own import file instead, base64-encoded in data.handoff.files. Taxprep and CCH iFirm take one .csv; TaxCycle takes one .xlsx workbook per form. 'gfi' returns the universal RC4088 .gfi file and takes no vendor.
handoff.languageone of en, frwhen handoff is setTaxprep import-file language: 'en' declares [Filemark|0|0] and 'fr' declares [Filemark|0|1]. It applies to Taxprep and CCH iFirm format 'file' projections and defaults to English, matching the persisted handoff-package route.
handoff.corporationNamestring, 1 to 200 characterswhen handoff is setCorporation name used to identify a format 'gfi' artifact. Optional on the selector, but format 'gfi' refuses when absent.
handoff.businessNumberstring, 9 to 32 characterswhen handoff is setCorporation BN9 or RC program-account number for the format 'gfi' header. Optional on the selector, but format 'gfi' refuses when absent or malformed.

Response

200. Versioned computation output shared by REST and MCP.

{
  "data": {
    "results": {
      "part_i_tax": {
        "ready": false,
        "provisional": false,
        "warnings": [],
        "<output cell>": "<any>"
      }
    },
    "result": {
      "ready": false,
      "provisional": false,
      "warnings": [],
      "<output cell>": "<any>"
    },
    "handoff": {
      "blocked": null,
      "warnings": [],
      "<output cell>": "<any>"
    },
    "vendorInput": {
      "vendor": "<taxcycle | taxprep>",
      "mappingTableVersion": "<string>",
      "vendorEdition": "<string>",
      "fieldMapVersion": "<string>",
      "applied": [
        {
          "cell": "<string>",
          "schedule": "<string>",
          "filemarkConcept": "<string>",
          "inputPath": "<string>",
          "cardinality": "one_to_one"
        }
      ]
    },
    "readiness": {
      "ready": false,
      "<output cell>": "<any>"
    },
    "<output cell>": "<any>"
  },
  "computeVersion": "<string>",
  "engineSchemaVersion": "<string>",
  "ratesVersion": "<string>",
  "timestamp": "2026-07-14T12:00:00Z"
}

Response fields

FieldTypeAlways presentDescription
dataobjectyesComputed target results and any requested handoff projection. Target results can publish ready, provisional, and warnings; saved-filing responses may also publish readiness. A handoff projection reports blocked when draft or unready results cannot be exported safely.
data.resultsmap of objectno
data.results.{key}objectper key
data.results.{key}.readybooleanper key
data.results.{key}.provisionalbooleanper key
data.results.{key}.warningsarray of anyper key
data.results.{key}.*anynoThe target's output cells; see the computation reference.
data.resultobjectno
data.result.readybooleanwhen result is set
data.result.provisionalbooleanwhen result is set
data.result.warningsarray of anywhen result is set
data.result.*anynoThe target's output cells; see the computation reference.
data.handoffobjectno
data.handoff.blockednullable objectwhen handoff is set
data.handoff.warningsarray of anywhen handoff is set
data.handoff.*anynoMembers not listed here.
data.vendorInputobjectnoMapping provenance for accepted vendor cells; present only when vendorInput was submitted. Values are never echoed.
data.vendorInput.vendorone of taxcycle, taxprepwhen vendorInput is set
data.vendorInput.mappingTableVersionstringwhen vendorInput is set
data.vendorInput.vendorEditionnullable stringwhen vendorInput is set
data.vendorInput.fieldMapVersionstringwhen vendorInput is set
data.vendorInput.appliedarray of objectswhen vendorInput is set
data.vendorInput.applied[].cellstringwhen vendorInput is set
data.vendorInput.applied[].schedulestringwhen vendorInput is set
data.vendorInput.applied[].filemarkConceptstringwhen vendorInput is set
data.vendorInput.applied[].inputPathstringwhen vendorInput is set
data.vendorInput.applied[].cardinalitystring, always "one_to_one"when vendorInput is set
data.readinessobjectno
data.readiness.readybooleanwhen readiness is set
data.readiness.*anynoMembers not listed here.
data.*anynoMembers not listed here.
computeVersionstringyes
engineSchemaVersionstringyes
ratesVersionstringyesContent hash of the rate-table sources and their verification manifest: the same pin the filing lane records. Two responses with equal computeVersion AND ratesVersion were computed on identical engine code and identical rate tables.
timestampstring (date-time)yes

Errors

The shared codes only; see error codes.

Compute a rollover or reorganization

POST /api/v1/computations/rollovers/{target}

Scope: tax:compute.

Request

curl --request POST https://api.filemark.ca/api/v1/computations/rollovers/section-22 \
  --header "Authorization: Bearer $FILEMARK_ACCESS_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "inputs": {
      "receivables": {
        "faceValue": 100000,
        "electedAmount": 80000,
        "vendorClaimedS20_1_pBefore": 0,
        "fairMarketValue": null,
        "vendorPriorS20_1_pDeductions": null
      },
      "party": {
        "jointElectionFiled": true,
        "soldAllOrSubstantiallyAllBusinessProperty": true,
        "purchaserProposesToContinueBusiness": true,
        "nonArmsLength": false
      }
    }
  }'
import os
import requests

FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]

response = requests.post(
    "https://api.filemark.ca/api/v1/computations/rollovers/section-22",
    headers={
        "Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
    },
    json={
        "inputs": {
            "receivables": {
                "faceValue": 100000,
                "electedAmount": 80000,
                "vendorClaimedS20_1_pBefore": 0,
                "fairMarketValue": None,
                "vendorPriorS20_1_pDeductions": None,
            },
            "party": {
                "jointElectionFiled": True,
                "soldAllOrSubstantiallyAllBusinessProperty": True,
                "purchaserProposesToContinueBusiness": True,
                "nonArmsLength": False,
            },
        },
    },
)
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/rollovers/section-22", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "inputs": {
      "receivables": {
        "faceValue": 100000,
        "electedAmount": 80000,
        "vendorClaimedS20_1_pBefore": 0,
        "fairMarketValue": null,
        "vendorPriorS20_1_pDeductions": null
      },
      "party": {
        "jointElectionFiled": true,
        "soldAllOrSubstantiallyAllBusinessProperty": true,
        "purchaserProposesToContinueBusiness": true,
        "nonArmsLength": false
      }
    }
  }),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());

Parameters

ParameterInTypeRequiredDescription
targetpathstringyes

Request body

Inputs for one rollover, reorganization, or screening engine.

FieldTypeRequiredDescription
inputsobjectnoCanonical rollover-engine inputs. Every member must be a published input cell of the target, with the published JSON type; unpublished members and wrong-typed cells are rejected with per-field details. Cell values beyond their JSON type are validated only under a payloadContract selector.
inputs.*anynoMembers not listed here.
payloadContractobjectnoOptional exact strict target contract. Omit this property to use the published legacy computation boundary; null is not valid.
payloadContract.boundaryProfileIdstring, 1 to 128 characters, matching ^[a-z][a-z0-9_.-]*$when payloadContract is setExact strict computation boundary profile identifier.
payloadContract.payloadSchemaVersionstring, up to 64 characters, matching ^[0-9]+\.[0-9]+\.[0-9]+$when payloadContract is setExact semantic version of the target payload schema pair.

Response

200. Versioned computation output shared by REST and MCP.

{
  "data": {
    "results": {
      "section-22": {
        "ready": false,
        "provisional": false,
        "warnings": [],
        "<output cell>": "<any>"
      }
    },
    "result": {
      "ready": false,
      "provisional": false,
      "warnings": [],
      "<output cell>": "<any>"
    },
    "handoff": {
      "blocked": null,
      "warnings": [],
      "<output cell>": "<any>"
    },
    "vendorInput": {
      "vendor": "<taxcycle | taxprep>",
      "mappingTableVersion": "<string>",
      "vendorEdition": "<string>",
      "fieldMapVersion": "<string>",
      "applied": [
        {
          "cell": "<string>",
          "schedule": "<string>",
          "filemarkConcept": "<string>",
          "inputPath": "<string>",
          "cardinality": "one_to_one"
        }
      ]
    },
    "readiness": {
      "ready": false,
      "<output cell>": "<any>"
    },
    "<output cell>": "<any>"
  },
  "computeVersion": "<string>",
  "engineSchemaVersion": "<string>",
  "ratesVersion": "<string>",
  "timestamp": "2026-07-14T12:00:00Z"
}

Response fields

FieldTypeAlways presentDescription
dataobjectyesComputed target results and any requested handoff projection. Target results can publish ready, provisional, and warnings; saved-filing responses may also publish readiness. A handoff projection reports blocked when draft or unready results cannot be exported safely.
data.resultsmap of objectno
data.results.{key}objectper key
data.results.{key}.readybooleanper key
data.results.{key}.provisionalbooleanper key
data.results.{key}.warningsarray of anyper key
data.results.{key}.*anynoThe target's output cells; see the computation reference.
data.resultobjectno
data.result.readybooleanwhen result is set
data.result.provisionalbooleanwhen result is set
data.result.warningsarray of anywhen result is set
data.result.*anynoThe target's output cells; see the computation reference.
data.handoffobjectno
data.handoff.blockednullable objectwhen handoff is set
data.handoff.warningsarray of anywhen handoff is set
data.handoff.*anynoMembers not listed here.
data.vendorInputobjectnoMapping provenance for accepted vendor cells; present only when vendorInput was submitted. Values are never echoed.
data.vendorInput.vendorone of taxcycle, taxprepwhen vendorInput is set
data.vendorInput.mappingTableVersionstringwhen vendorInput is set
data.vendorInput.vendorEditionnullable stringwhen vendorInput is set
data.vendorInput.fieldMapVersionstringwhen vendorInput is set
data.vendorInput.appliedarray of objectswhen vendorInput is set
data.vendorInput.applied[].cellstringwhen vendorInput is set
data.vendorInput.applied[].schedulestringwhen vendorInput is set
data.vendorInput.applied[].filemarkConceptstringwhen vendorInput is set
data.vendorInput.applied[].inputPathstringwhen vendorInput is set
data.vendorInput.applied[].cardinalitystring, always "one_to_one"when vendorInput is set
data.readinessobjectno
data.readiness.readybooleanwhen readiness is set
data.readiness.*anynoMembers not listed here.
data.*anynoMembers not listed here.
computeVersionstringyes
engineSchemaVersionstringyes
ratesVersionstringyesContent hash of the rate-table sources and their verification manifest: the same pin the filing lane records. Two responses with equal computeVersion AND ratesVersion were computed on identical engine code and identical rate tables.
timestampstring (date-time)yes

Errors

The shared codes only; see error codes.

Filemark | REST reference