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.
| Resource | Operation | Method and path | Scope |
|---|---|---|---|
| Clients | List clients | GET /api/v1/clients | clients:read |
| Clients | Get a client | GET /api/v1/clients/{client_id} | clients:read |
| Clients | List a client's entities | GET /api/v1/clients/{client_id}/entities | entities:read |
| Entities | Get an entity | GET /api/v1/entities/{entity_id} | entities:read |
| Entities | List an entity's tax years | GET /api/v1/entities/{entity_id}/tax-years | tax-years:read |
| Tax years | Get a tax year | GET /api/v1/tax-years/{tax_year_id} | tax-years:read |
| Search | Search engagement records | GET /api/v1/search | engagements:read |
| Engagements | List engagements | GET /api/v1/engagements | engagements:read |
| Engagements | Get an engagement | GET /api/v1/engagements/{engagement_id} | engagements:read |
| Engagements | Get engagement context | GET /api/v1/engagements/{engagement_id}/context | engagements:read |
| Engagements | Get engagement history | GET /api/v1/engagements/{engagement_id}/history | engagements:read |
| Engagements | List engagement documents | GET /api/v1/engagements/{engagement_id}/documents | documents:read |
| Engagements | List engagement workpapers | GET /api/v1/engagements/{engagement_id}/workpapers | workpapers:read |
| Engagements | Get engagement review summary | GET /api/v1/engagements/{engagement_id}/review-summary | review:read |
| Engagement forms | Get an engagement form catalog | GET /api/v1/engagements/{engagement_id}/forms | engagements:read |
| Saved tax data | Get a saved trial balance | GET /api/v1/engagements/{engagement_id}/trial-balance | tax-data:read |
| Saved accounts | Get a saved engagement account | GET /api/v1/engagements/{engagement_id}/accounts/{account_id} | tax-data:read |
| Saved accounts | List saved account adjustments | GET /api/v1/engagements/{engagement_id}/accounts/{account_id}/adjustments | tax-data:read |
| Saved-state computations | Compute an engagement's saved state with cells replaced | POST /api/v1/engagements/{engagement_id}/computations/scenario | tax-data:read + tax:compute |
| Computations | List computation targets | GET /api/v1/computations | tax:compute |
| Computations | Get a computation target contract | GET /api/v1/computations/targets/{target_id} | tax:compute |
| Computations | Compute tax schedules | POST /api/v1/computations/batch | tax:compute |
| Computations | Compute a rollover or reorganization | POST /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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
limit | query | integer, 1 to 200, default 50 | no | Page size (1-200). |
offset | query | integer, 0 to 100000, default 0 | no | Zero-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
| Field | Type | Always present | Description |
|---|---|---|---|
data | array of objects | yes | |
data[].id | string (uuid) | yes | Stable UUID of the client. |
data[].name | string | yes | Client display name. |
data[].createdAt | string (date-time) | yes | ISO-8601 creation timestamp (UTC). |
data[].updatedAt | string (date-time) | yes | ISO-8601 last-modified timestamp (UTC). |
pagination | object | yes | Offset pagination retained for the original client-list contract. |
pagination.limit | integer | yes | Page size actually applied (1-200). |
pagination.offset | integer | yes | Zero-based row offset (max 100,000). |
pagination.total | integer | yes | Total matching resources in the organization. |
pagination.hasMore | boolean | yes | True 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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
client_id | path | string (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
| Field | Type | Always present | Description |
|---|---|---|---|
id | string (uuid) | yes | Stable UUID of the client. |
name | string | yes | Client display name. |
createdAt | string (date-time) | yes | ISO-8601 creation timestamp (UTC). |
updatedAt | string (date-time) | yes | ISO-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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
client_id | path | string (uuid) | yes | |
limit | query | integer, 1 to 200, default 50 | no | Page size (1-200). |
cursor | query | nullable string, 1 to 4096 characters | no | Opaque 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
| Field | Type | Always present | Description |
|---|---|---|---|
data | array of objects | yes | |
data[].id | string (uuid) | yes | Stable UUID of the entity. |
data[].clientId | string (uuid) | yes | UUID of the entity's parent client. |
data[].name | string | yes | Entity display name. |
data[].legalName | nullable string | no | Registered legal name, when known. |
data[].corporationNumber | nullable string | no | Corporate registry number, when known. |
data[].businessNumber | nullable string | no | Canadian business number, when known. |
data[].naicsCode | nullable string | no | NAICS industry code, when assigned. |
data[].dissolvedAt | nullable string (date) | no | Entity dissolution date, when applicable. |
data[].incorporationJurisdiction | nullable string | no | Corporate-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[].incorporationDate | nullable string (date) | no | Date the current incorporationJurisdiction took effect: original incorporation, or the most recent continuance into that jurisdiction. Null when not recorded. |
pagination | object | yes | Opaque keyset pagination for new v1 collection endpoints. |
pagination.limit | integer | yes | Page size actually applied (1-200). |
pagination.nextCursor | nullable string | no | Opaque cursor for the next page; null on the final page. |
pagination.hasMore | boolean | yes | True 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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
entity_id | path | string (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
| Field | Type | Always present | Description |
|---|---|---|---|
id | string (uuid) | yes | Stable UUID of the entity. |
clientId | string (uuid) | yes | UUID of the entity's parent client. |
name | string | yes | Entity display name. |
legalName | nullable string | no | Registered legal name, when known. |
corporationNumber | nullable string | no | Corporate registry number, when known. |
businessNumber | nullable string | no | Canadian business number, when known. |
naicsCode | nullable string | no | NAICS industry code, when assigned. |
dissolvedAt | nullable string (date) | no | Entity dissolution date, when applicable. |
incorporationJurisdiction | nullable string | no | Corporate-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. |
incorporationDate | nullable string (date) | no | Date 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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
entity_id | path | string (uuid) | yes | |
limit | query | integer, 1 to 200, default 50 | no | Page size (1-200). |
cursor | query | nullable string, 1 to 4096 characters | no | Opaque 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
| Field | Type | Always present | Description |
|---|---|---|---|
data | array of objects | yes | |
data[].id | string (uuid) | yes | Stable UUID of the tax-year engagement. |
data[].entityId | string (uuid) | yes | UUID of the parent entity. |
data[].clientId | string (uuid) | yes | UUID of the parent client. |
data[].yearEnd | string (date) | yes | Fiscal year-end date. |
data[].periodStart | nullable string (date) | no | Fiscal period start date; null only for legacy records. |
data[].status | one of in_progress, review, complete | yes | Current engagement workflow status. |
data[].source | one of prepared, imported | yes | Prepared binder or imported prior-year reference. |
data[].engagementType | nullable one of compilation, review, audit, tax_only | no | Engagement service type, when assigned. |
data[].priorYearTaxYearId | nullable string (uuid) | no | Linked prior tax year used for comparatives, when present. |
data[].createdAt | string (date-time) | yes | ISO-8601 creation timestamp (UTC). |
data[].lastModifiedAt | string (date-time) | yes | ISO-8601 last-modified timestamp (UTC). |
pagination | object | yes | Opaque keyset pagination for new v1 collection endpoints. |
pagination.limit | integer | yes | Page size actually applied (1-200). |
pagination.nextCursor | nullable string | no | Opaque cursor for the next page; null on the final page. |
pagination.hasMore | boolean | yes | True 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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
tax_year_id | path | string (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
| Field | Type | Always present | Description |
|---|---|---|---|
id | string (uuid) | yes | Stable UUID of the tax-year engagement. |
entityId | string (uuid) | yes | UUID of the parent entity. |
clientId | string (uuid) | yes | UUID of the parent client. |
yearEnd | string (date) | yes | Fiscal year-end date. |
periodStart | nullable string (date) | no | Fiscal period start date; null only for legacy records. |
status | one of in_progress, review, complete | yes | Current engagement workflow status. |
source | one of prepared, imported | yes | Prepared binder or imported prior-year reference. |
engagementType | nullable one of compilation, review, audit, tax_only | no | Engagement service type, when assigned. |
priorYearTaxYearId | nullable string (uuid) | no | Linked prior tax year used for comparatives, when present. |
createdAt | string (date-time) | yes | ISO-8601 creation timestamp (UTC). |
lastModifiedAt | string (date-time) | yes | ISO-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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
q | query | string, 2 to 80 characters | yes | Two to eighty characters and at most six whitespace-separated terms. ILIKE wildcard characters are matched literally. |
year_end | query | nullable string (date) | no | Optional exact taxation-year end date. |
status | query | nullable one of in_progress, review, complete | no | Optional workflow-status filter. |
limit | query | integer, 1 to 25, default 10 | no | Shortlist 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
| Field | Type | Always present | Description |
|---|---|---|---|
query | string, 2 to 80 characters | yes | |
resolution | one of no_match, unique, ambiguous | yes | |
data | array of objects, up to 25 items | yes | |
data[].id | string (uuid) | yes | |
data[].client | object | yes | Safe identity fields for an engagement's client or entity. |
data[].client.id | string (uuid) | yes | |
data[].client.name | string | yes | |
data[].client.legalName | nullable string | no | |
data[].entity | object | yes | Safe identity fields for an engagement's client or entity. |
data[].entity.id | string (uuid) | yes | |
data[].entity.name | string | yes | |
data[].entity.legalName | nullable string | no | |
data[].yearEnd | string (date) | yes | |
data[].periodStart | nullable string (date) | no | |
data[].status | one of in_progress, review, complete | yes | |
data[].source | one of prepared, imported | yes | |
data[].engagementType | nullable one of compilation, review, audit, tax_only | no | |
data[].priorYearEngagementId | nullable string (uuid) | no | |
data[].isLocked | boolean | yes | |
data[].lifecycle | object | yes | Non-sensitive return lifecycle metadata. |
data[].lifecycle.filedAt | nullable string (date-time) | no | |
data[].lifecycle.revisionNumber | integer, at least 1 | yes | |
data[].lifecycle.parentEngagementId | nullable string (uuid) | no | |
data[].lifecycle.amendedByEngagementId | nullable string (uuid) | no | |
data[].createdAt | string (date-time) | yes | |
data[].updatedAt | string (date-time) | yes | |
pagination | object | yes | Metadata for one bounded search shortlist. |
pagination.limit | integer, 1 to 25 | yes | Result limit actually applied. |
pagination.hasMore | boolean | yes | True 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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
client_id | query | nullable string (uuid) | no | Optional organization-owned client filter. |
entity_id | query | nullable string (uuid) | no | Optional organization-owned legal-entity filter. |
year_end | query | nullable string (date) | no | Optional exact taxation-year end date. |
status | query | nullable one of in_progress, review, complete | no | Optional workflow-status filter. |
limit | query | integer, 1 to 200, default 50 | no | Page size (1-200). |
cursor | query | nullable string, 1 to 4096 characters | no | Opaque 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
| Field | Type | Always present | Description |
|---|---|---|---|
data | array of objects | yes | |
data[].id | string (uuid) | yes | |
data[].client | object | yes | Safe identity fields for an engagement's client or entity. |
data[].client.id | string (uuid) | yes | |
data[].client.name | string | yes | |
data[].client.legalName | nullable string | no | |
data[].entity | object | yes | Safe identity fields for an engagement's client or entity. |
data[].entity.id | string (uuid) | yes | |
data[].entity.name | string | yes | |
data[].entity.legalName | nullable string | no | |
data[].yearEnd | string (date) | yes | |
data[].periodStart | nullable string (date) | no | |
data[].status | one of in_progress, review, complete | yes | |
data[].source | one of prepared, imported | yes | |
data[].engagementType | nullable one of compilation, review, audit, tax_only | no | |
data[].priorYearEngagementId | nullable string (uuid) | no | |
data[].isLocked | boolean | yes | |
data[].lifecycle | object | yes | Non-sensitive return lifecycle metadata. |
data[].lifecycle.filedAt | nullable string (date-time) | no | |
data[].lifecycle.revisionNumber | integer, at least 1 | yes | |
data[].lifecycle.parentEngagementId | nullable string (uuid) | no | |
data[].lifecycle.amendedByEngagementId | nullable string (uuid) | no | |
data[].createdAt | string (date-time) | yes | |
data[].updatedAt | string (date-time) | yes | |
pagination | object | yes | Opaque keyset pagination for new v1 collection endpoints. |
pagination.limit | integer | yes | Page size actually applied (1-200). |
pagination.nextCursor | nullable string | no | Opaque cursor for the next page; null on the final page. |
pagination.hasMore | boolean | yes | True 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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
engagement_id | path | string (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
| Field | Type | Always present | Description |
|---|---|---|---|
id | string (uuid) | yes | |
client | object | yes | Safe identity fields for an engagement's client or entity. |
client.id | string (uuid) | yes | |
client.name | string | yes | |
client.legalName | nullable string | no | |
entity | object | yes | Safe identity fields for an engagement's client or entity. |
entity.id | string (uuid) | yes | |
entity.name | string | yes | |
entity.legalName | nullable string | no | |
yearEnd | string (date) | yes | |
periodStart | nullable string (date) | no | |
status | one of in_progress, review, complete | yes | |
source | one of prepared, imported | yes | |
engagementType | nullable one of compilation, review, audit, tax_only | no | |
priorYearEngagementId | nullable string (uuid) | no | |
isLocked | boolean | yes | |
lifecycle | object | yes | Non-sensitive return lifecycle metadata. |
lifecycle.filedAt | nullable string (date-time) | no | |
lifecycle.revisionNumber | integer, at least 1 | yes | |
lifecycle.parentEngagementId | nullable string (uuid) | no | |
lifecycle.amendedByEngagementId | nullable string (uuid) | no | |
createdAt | string (date-time) | yes | |
updatedAt | string (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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
engagement_id | path | string (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
| Field | Type | Always present | Description |
|---|---|---|---|
requestedEngagement | object | yes | One tax-year engagement, without financial or tax-return payloads. |
requestedEngagement.id | string (uuid) | yes | |
requestedEngagement.client | object | yes | Safe identity fields for an engagement's client or entity. |
requestedEngagement.client.id | string (uuid) | yes | |
requestedEngagement.client.name | string | yes | |
requestedEngagement.client.legalName | nullable string | no | |
requestedEngagement.entity | object | yes | Safe identity fields for an engagement's client or entity. |
requestedEngagement.entity.id | string (uuid) | yes | |
requestedEngagement.entity.name | string | yes | |
requestedEngagement.entity.legalName | nullable string | no | |
requestedEngagement.yearEnd | string (date) | yes | |
requestedEngagement.periodStart | nullable string (date) | no | |
requestedEngagement.status | one of in_progress, review, complete | yes | |
requestedEngagement.source | one of prepared, imported | yes | |
requestedEngagement.engagementType | nullable one of compilation, review, audit, tax_only | no | |
requestedEngagement.priorYearEngagementId | nullable string (uuid) | no | |
requestedEngagement.isLocked | boolean | yes | |
requestedEngagement.lifecycle | object | yes | Non-sensitive return lifecycle metadata. |
requestedEngagement.lifecycle.filedAt | nullable string (date-time) | no | |
requestedEngagement.lifecycle.revisionNumber | integer, at least 1 | yes | |
requestedEngagement.lifecycle.parentEngagementId | nullable string (uuid) | no | |
requestedEngagement.lifecycle.amendedByEngagementId | nullable string (uuid) | no | |
requestedEngagement.createdAt | string (date-time) | yes | |
requestedEngagement.updatedAt | string (date-time) | yes | |
currentEngagement | object | yes | One tax-year engagement, without financial or tax-return payloads. |
currentEngagement.id | string (uuid) | yes | |
currentEngagement.client | object | yes | Safe identity fields for an engagement's client or entity. |
currentEngagement.client.id | string (uuid) | yes | |
currentEngagement.client.name | string | yes | |
currentEngagement.client.legalName | nullable string | no | |
currentEngagement.entity | object | yes | Safe identity fields for an engagement's client or entity. |
currentEngagement.entity.id | string (uuid) | yes | |
currentEngagement.entity.name | string | yes | |
currentEngagement.entity.legalName | nullable string | no | |
currentEngagement.yearEnd | string (date) | yes | |
currentEngagement.periodStart | nullable string (date) | no | |
currentEngagement.status | one of in_progress, review, complete | yes | |
currentEngagement.source | one of prepared, imported | yes | |
currentEngagement.engagementType | nullable one of compilation, review, audit, tax_only | no | |
currentEngagement.priorYearEngagementId | nullable string (uuid) | no | |
currentEngagement.isLocked | boolean | yes | |
currentEngagement.lifecycle | object | yes | Non-sensitive return lifecycle metadata. |
currentEngagement.lifecycle.filedAt | nullable string (date-time) | no | |
currentEngagement.lifecycle.revisionNumber | integer, at least 1 | yes | |
currentEngagement.lifecycle.parentEngagementId | nullable string (uuid) | no | |
currentEngagement.lifecycle.amendedByEngagementId | nullable string (uuid) | no | |
currentEngagement.createdAt | string (date-time) | yes | |
currentEngagement.updatedAt | string (date-time) | yes | |
revision | object | yes | Safe amendment-chain relationships for one requested engagement. |
revision.rootEngagementId | string (uuid) | yes | |
revision.previousEngagementId | nullable string (uuid) | no | |
revision.nextEngagementId | nullable string (uuid) | no | |
revision.currentEngagementId | string (uuid) | yes | |
revision.isCurrent | boolean | yes |
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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
engagement_id | path | string (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
| Field | Type | Always present | Description |
|---|---|---|---|
engagementId | string (uuid) | yes | |
currentEngagementId | string (uuid) | yes | |
revisions | array of objects, 1 to 100 items | yes | |
revisions[].id | string (uuid) | yes | |
revisions[].client | object | yes | Safe identity fields for an engagement's client or entity. |
revisions[].client.id | string (uuid) | yes | |
revisions[].client.name | string | yes | |
revisions[].client.legalName | nullable string | no | |
revisions[].entity | object | yes | Safe identity fields for an engagement's client or entity. |
revisions[].entity.id | string (uuid) | yes | |
revisions[].entity.name | string | yes | |
revisions[].entity.legalName | nullable string | no | |
revisions[].yearEnd | string (date) | yes | |
revisions[].periodStart | nullable string (date) | no | |
revisions[].status | one of in_progress, review, complete | yes | |
revisions[].source | one of prepared, imported | yes | |
revisions[].engagementType | nullable one of compilation, review, audit, tax_only | no | |
revisions[].priorYearEngagementId | nullable string (uuid) | no | |
revisions[].isLocked | boolean | yes | |
revisions[].lifecycle | object | yes | Non-sensitive return lifecycle metadata. |
revisions[].lifecycle.filedAt | nullable string (date-time) | no | |
revisions[].lifecycle.revisionNumber | integer, at least 1 | yes | |
revisions[].lifecycle.parentEngagementId | nullable string (uuid) | no | |
revisions[].lifecycle.amendedByEngagementId | nullable string (uuid) | no | |
revisions[].createdAt | string (date-time) | yes | |
revisions[].updatedAt | string (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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
engagement_id | path | string (uuid) | yes | |
limit | query | integer, 1 to 200, default 50 | no | Page size (1-200). |
offset | query | integer, 0 to 100000, default 0 | no | Zero-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
| Field | Type | Always present | Description |
|---|---|---|---|
data | array of objects | yes | |
data[].id | string, 1 to 256 characters | yes | |
data[].fileName | string, 1 to 512 characters | yes | |
data[].kind | one of gl, fs, workpaper, supporting, tb-current, tb-prior, tb-classification, gifi-export, prior-return, portal-upload, evidence | yes | |
data[].source | one of onboarding, manual, portal, connector, unknown | yes | |
data[].uploadedAt | nullable string (date-time) | no | |
pagination | object | yes | Bounded offset-pagination metadata. |
pagination.limit | integer, 1 to 200 | yes | Page size actually applied. |
pagination.offset | integer, 0 to 100000 | yes | Zero-based row offset actually applied. |
pagination.total | integer, at least 0 | yes | Total matching resources. |
pagination.hasMore | boolean | yes | True 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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
engagement_id | path | string (uuid) | yes | |
limit | query | integer, 1 to 200, default 50 | no | Page size (1-200). |
offset | query | integer, 0 to 100000, default 0 | no | Zero-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
| Field | Type | Always present | Description |
|---|---|---|---|
data | array of objects | yes | |
data[].id | string (uuid) | yes | |
data[].templateId | nullable string | no | |
data[].kind | string | yes | |
data[].origin | string | yes | |
data[].status | string | yes | |
data[].parseStatus | nullable string | no | |
data[].tieOutMode | nullable string | no | |
data[].tieOutStatus | nullable string | no | |
data[].detectedType | nullable string | no | |
data[].category | nullable string | no | |
data[].version | integer, at least 1 | yes | |
data[].isReviewed | boolean | yes | |
data[].reviewedAt | nullable string (date-time) | no | |
data[].sourceFileName | nullable string, up to 512 characters | no | |
data[].linkedAccountCount | integer, at least 0 | yes | |
data[].createdAt | string (date-time) | yes | |
data[].updatedAt | string (date-time) | yes | |
pagination | object | yes | Bounded offset-pagination metadata. |
pagination.limit | integer, 1 to 200 | yes | Page size actually applied. |
pagination.offset | integer, 0 to 100000 | yes | Zero-based row offset actually applied. |
pagination.total | integer, at least 0 | yes | Total matching resources. |
pagination.hasMore | boolean | yes | True 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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
engagement_id | path | string (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
| Field | Type | Always present | Description |
|---|---|---|---|
engagementId | string (uuid) | yes | |
engagementStatus | one of in_progress, review, complete | yes | |
lifecycleStatus | one of open, signed, filed | yes | |
signoffs | object | yes | |
signoffs.preparerSigned | boolean | yes | |
signoffs.reviewerSigned | boolean | yes | |
signoffs.reviewerStatus | one of pending, signed, skipped | yes | |
signoffs.partnerSigned | boolean | yes | |
workpapers | object | yes | |
workpapers.total | integer, at least 0 | yes | |
workpapers.reviewed | integer, at least 0 | yes | |
workpapers.tieOutMatched | integer, at least 0 | yes | |
workpapers.tieOutDifference | integer, at least 0 | yes | |
workpapers.tieOutIncomplete | integer, at least 0 | yes | |
workpapers.tieOutPending | integer, at least 0 | yes | |
accountReviewStatuses | object | yes | |
accountReviewStatuses.followUp | integer, at least 0 | yes | |
accountReviewStatuses.analyzed | integer, at least 0 | yes | |
accountReviewStatuses.firstReview | integer, at least 0 | yes | |
accountReviewStatuses.secondReview | integer, at least 0 | yes | |
activeReviewMarks | object | yes | |
activeReviewMarks.total | integer, at least 0 | yes | |
activeReviewMarks.questions | integer, at least 0 | yes | |
activeReviewMarks.corrections | integer, at least 0 | yes | |
activeReviewMarks.firstReview | integer, at least 0 | yes | |
activeReviewMarks.partnerReview | integer, at least 0 | yes | |
acknowledgedWarningCount | integer, at least 0 | yes | |
readiness | object | yes | Readiness state when no authoritative result is persisted. |
readiness.evaluated | boolean, always false | no | |
readiness.ready | null | no |
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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
engagement_id | path | string (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
| Field | Type | Always present | Description |
|---|---|---|---|
context | object | yes | Safe engagement context pinned to the exact requested revision. |
context.engagementId | string (uuid) | yes | |
context.yearEnd | string (date) | yes | |
context.taxYear | integer, 1900 to 9999 | yes | |
context.revisionNumber | integer, at least 1 | yes | |
context.source | one of prepared, imported | yes | |
context.filedAt | nullable string (date-time) | yes | |
context.referenceOnly | boolean | yes | |
data | array of objects, up to 200 items | yes | |
data[].targetId | string, matching ^(?:S\d+[A-Z]?|T\d+[A-Z]?)$ | yes | |
data[].displayName | string, 1 to 256 characters | yes | |
data[].formId | string, matching ^[A-Z0-9_-]{1,64}$ | yes | |
data[].taxYearWindow | object | yes | Inclusive tax-year support window from the canonical registry. |
data[].taxYearWindow.from | integer, 1900 to 9999 | yes | |
data[].taxYearWindow.through | nullable integer, 1900 to 9999 | yes | |
data[].availability | string, always "supported" | yes | |
data[].applicabilityBasis | string, always "tax_year_window" | yes | |
data[].filingRequirement | string, always "not_evaluated" | yes | |
evaluation | object | yes | Permanent sentinels preventing catalog discovery from implying results. |
evaluation.formRevisionResolved | boolean, always false | yes | |
evaluation.savedStateEvaluated | boolean, always false | yes | |
evaluation.computationEvaluated | boolean, always false | yes | |
evaluation.readinessEvaluated | boolean, always false | yes |
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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
engagement_id | path | string (uuid) | yes | |
limit | query | integer, 1 to 200, default 50 | no | Maximum active accounts to return (1-200). |
cursor | query | nullable string, 1 to 4096 characters | no | Opaque 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
| Field | Type | Always present | Description |
|---|---|---|---|
context | object | yes | |
context.engagementId | string (uuid) | yes | |
context.yearEnd | string (date) | yes | |
context.revisionNumber | integer, at least 1 | yes | |
context.status | one of in_progress, review, complete | yes | |
context.source | one of prepared, imported | yes | |
context.filedAt | nullable string (date-time) | yes | |
context.referenceOnly | boolean | yes | |
context.reportingCurrency | string, matching ^[A-Z]{3}$ | yes | |
context.currencyBasis | one of canadian_currency, functional_currency, reversionary | yes | |
context.balanceConvention | string, always "debits_positive_credits_negative" | yes | |
sourceRevision | object | yes | Version vector and content address for the exact saved projection. |
sourceRevision.classifiedReportVersion | integer, at least 0 | yes | |
sourceRevision.gifiAssignmentsVersion | integer, at least 0 | yes | |
sourceRevision.lastModifiedAt | string (date-time) | yes | |
sourceRevision.snapshotDigest | string, matching ^sha256:[0-9a-f]{64}$ | yes | |
availability | one of available, empty, not_imported | yes | |
projection | object | yes | Semantic sentinels that prevent consumers from assuming extra state. |
projection.savedBookBalancesIncluded | boolean, always true | yes | |
projection.gifiAssignmentsIncluded | boolean, always true | yes | |
projection.archivedAccountsIncluded | boolean, always false | yes | |
projection.postedBookAdjustmentsIncluded | boolean, always false | yes | |
projection.taxAdjustmentsIncluded | boolean, always false | yes | |
projection.classificationIncluded | boolean, always false | yes | |
projection.computationEvaluated | boolean, always false | yes | |
projection.lineageIncluded | boolean, always false | yes | |
projection.readinessEvaluated | boolean, always false | yes | |
totalStoredAccountCount | integer, at least 0 | yes | |
archivedAccountCount | integer, at least 0 | yes | |
data | array of objects, up to 200 items | yes | |
data[].id | string, 1 to 128 characters | yes | |
data[].accountCode | nullable string, up to 128 characters | yes | |
data[].accountName | string, up to 512 characters | yes | |
data[].currentYearBalance | decimal string, 1 to 96 characters | yes | Exact base-10 amount in the engagement reporting currency. |
data[].priorYearBalance | nullable decimal string, 1 to 96 characters | yes | |
data[].gifiCode | nullable string, matching ^[0-9]{4}$ | yes | |
data[].changeStatus | one of new, removed, significant_increase, significant_decrease, minor_change, unchanged, unknown | yes | |
pagination | object | yes | |
pagination.limit | integer, 1 to 200 | yes | |
pagination.total | integer, at least 0 | yes | |
pagination.nextCursor | nullable string | yes | |
pagination.hasMore | boolean | yes |
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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
engagement_id | path | string (uuid) | yes | |
account_id | path | string, 1 to 128 characters | yes |
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
| Field | Type | Always present | Description |
|---|---|---|---|
context | object | yes | |
context.engagementId | string (uuid) | yes | |
context.yearEnd | string (date) | yes | |
context.revisionNumber | integer, at least 1 | yes | |
context.status | one of in_progress, review, complete | yes | |
context.source | one of prepared, imported | yes | |
context.filedAt | nullable string (date-time) | yes | |
context.referenceOnly | boolean | yes | |
context.reportingCurrency | string, matching ^[A-Z]{3}$ | yes | |
context.currencyBasis | one of canadian_currency, functional_currency, reversionary | yes | |
context.balanceConvention | string, always "debits_positive_credits_negative" | yes | |
sourceRevision | object | yes | |
sourceRevision.classifiedReportVersion | integer, at least 0 | yes | |
sourceRevision.gifiAssignmentsVersion | integer, at least 0 | yes | |
sourceRevision.gifiCarriedForwardVersion | integer, at least 0 | yes | |
sourceRevision.gifiAutoAppliedAccountIdsVersion | integer, at least 0 | yes | |
sourceRevision.ajeEntriesVersion | integer, at least 0 | yes | |
sourceRevision.lastModifiedAt | string (date-time) | yes | |
sourceRevision.workpaperRevisionDigest | string, matching ^sha256:[0-9a-f]{64}$ | yes | |
sourceRevision.snapshotDigest | string, matching ^sha256:[0-9a-f]{64}$ | yes | |
account | object | yes | |
account.id | string, 1 to 128 characters | yes | |
account.accountCode | nullable string, up to 128 characters | yes | |
account.accountName | string, up to 512 characters | yes | |
account.currentYearBalance | decimal string, 1 to 96 characters | yes | Exact base-10 amount in the engagement reporting currency. |
account.priorYearBalance | nullable decimal string, 1 to 96 characters | yes | |
account.changeStatus | one of new, removed, significant_increase, significant_decrease, minor_change, unchanged, unknown | yes | |
classification | object | yes | |
classification.availability | one of classified, not_classified | yes | |
classification.userStatus | nullable one of pending, modified, accepted | yes | |
classification.ruleId | nullable string, up to 256 characters | yes | |
classification.source | nullable one of rule, prior_year, llm, llm_failed, manual | yes | |
classification.confidence | nullable decimal string, 1 to 96 characters | yes | |
classification.assumption | nullable string, up to 4000 characters | yes | |
classification.bookTreatment | nullable one of accept_as_booked, reclassify, accrue_adjust, write_off, requires_review, unclassified | yes | |
classification.taxTreatment | nullable one of fully_deductible, non_deductible_full, partially_deductible, capital_cca, timing_difference, deduct_other_schedule, non_taxable, disclosure_only, informational, unclassified | yes | |
classification.bookTreatmentSource | nullable one of derived, manual | yes | |
classification.taxTreatmentSource | nullable one of derived, manual | yes | |
classification.s1Line | nullable string, up to 32 characters | yes | |
classification.feedsSchedule | nullable string, up to 32 characters | yes | |
classification.taxAssumptionNote | nullable string, up to 4000 characters | yes | |
classification.derivationRuleId | nullable string, up to 256 characters | yes | |
classification.adjustmentType | nullable one of addition, deduction | yes | |
classification.deductibilityRule | nullable string, up to 2000 characters | yes | |
classification.deductibilityPercentage | nullable decimal string, 1 to 96 characters | yes | |
classification.incomeType | nullable one of active_business, property, rental, capital | yes | |
classification.incomeTypeSource | nullable one of derived, manual | yes | |
classification.foreignSource | nullable boolean | yes | |
classification.subtype | nullable string, up to 64 characters | yes | |
classification.conditionalOn | nullable string, up to 2000 characters | yes | |
classification.templateId | nullable string, up to 256 characters | yes | |
classification.itaReferences | array of strings, up to 32 items | yes | |
gifiMapping | object | yes | |
gifiMapping.assignedGifiCode | nullable string, matching ^[0-9]{4}$ | yes | |
gifiMapping.carriedForward | boolean | yes | |
gifiMapping.machineApplied | boolean | yes | |
gifiMapping.relationToCurrentDefault | one of unassigned, no_default, matches_default, overrides_default | yes | |
gifiMapping.chartAccount | nullable object | yes | |
gifiMapping.chartAccount.id | string (uuid) | when chartAccount is set | |
gifiMapping.chartAccount.naturalKey | string, 1 to 517 characters | when chartAccount is set | |
gifiMapping.chartAccount.accountType | one of asset, liability, equity, revenue, expense, unassigned | when chartAccount is set | |
gifiMapping.chartAccount.accountSubtype | nullable string, up to 256 characters | when chartAccount is set | |
gifiMapping.chartAccount.subtypeSource | nullable string, up to 64 characters | when chartAccount is set | |
gifiMapping.chartAccount.accountTypeSource | one of inferred, firm_template, connector, coa_file, user | when chartAccount is set | |
gifiMapping.chartAccount.isContra | boolean | when chartAccount is set | |
gifiMapping.chartAccount.isActive | boolean | when chartAccount is set | |
gifiMapping.chartAccount.defaultGifiCode | nullable string, matching ^[0-9]{4}$ | when chartAccount is set | |
gifiMapping.chartAccount.defaultGifiSource | nullable one of inferred, firm_template, carried, connector, coa_file, user | when chartAccount is set | |
gifiMapping.chartAccount.parentAccountCode | nullable string, up to 128 characters | when chartAccount is set | |
gifiMapping.chartAccount.updatedAt | string (date-time) | when chartAccount is set | |
adjustmentSummary | object | yes | |
adjustmentSummary.postedBookAdjustmentTotal | decimal string, 1 to 96 characters | yes | Exact base-10 amount in the engagement reporting currency. |
adjustmentSummary.adjustedBookBalance | decimal string, 1 to 96 characters | yes | Exact base-10 amount in the engagement reporting currency. |
adjustmentSummary.postedBookAdjustmentCount | integer, at least 0 | yes | |
adjustmentSummary.blockedBookAdjustmentCount | integer, at least 0 | yes | |
adjustmentSummary.workpaperTaxAdjustmentSourceCount | integer, at least 0 | yes | |
adjustmentSummary.schedule1ImpactEvaluated | boolean, always false | yes | |
projection | object | yes | |
projection.savedStateOnly | boolean, always true | yes | |
projection.classificationIncluded | boolean, always true | yes | |
projection.gifiMappingIncluded | boolean, always true | yes | |
projection.postedBookAdjustmentsSummarized | boolean, always true | yes | |
projection.workpaperTaxAdjustmentsSummarized | boolean, always true | yes | |
projection.workpaperAmountsAllocatedToAccount | boolean, always false | yes | |
projection.schedule1ImpactEvaluated | boolean, always false | yes | |
projection.computationEvaluated | boolean, always false | yes | |
projection.lineageIncluded | boolean, always false | yes | |
projection.readinessEvaluated | boolean, always false | yes | |
projection.storageMetadataIncluded | boolean, always false | yes |
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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
engagement_id | path | string (uuid) | yes | |
account_id | path | string, 1 to 128 characters | yes |
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
| Field | Type | Always present | Description |
|---|---|---|---|
context | object | yes | |
context.engagementId | string (uuid) | yes | |
context.yearEnd | string (date) | yes | |
context.revisionNumber | integer, at least 1 | yes | |
context.status | one of in_progress, review, complete | yes | |
context.source | one of prepared, imported | yes | |
context.filedAt | nullable string (date-time) | yes | |
context.referenceOnly | boolean | yes | |
context.reportingCurrency | string, matching ^[A-Z]{3}$ | yes | |
context.currencyBasis | one of canadian_currency, functional_currency, reversionary | yes | |
context.balanceConvention | string, always "debits_positive_credits_negative" | yes | |
sourceRevision | object | yes | |
sourceRevision.classifiedReportVersion | integer, at least 0 | yes | |
sourceRevision.gifiAssignmentsVersion | integer, at least 0 | yes | |
sourceRevision.gifiCarriedForwardVersion | integer, at least 0 | yes | |
sourceRevision.gifiAutoAppliedAccountIdsVersion | integer, at least 0 | yes | |
sourceRevision.ajeEntriesVersion | integer, at least 0 | yes | |
sourceRevision.lastModifiedAt | string (date-time) | yes | |
sourceRevision.workpaperRevisionDigest | string, matching ^sha256:[0-9a-f]{64}$ | yes | |
sourceRevision.snapshotDigest | string, matching ^sha256:[0-9a-f]{64}$ | yes | |
account | object | yes | |
account.id | string, 1 to 128 characters | yes | |
account.accountCode | nullable string, up to 128 characters | yes | |
account.accountName | string, up to 512 characters | yes | |
account.currentYearBalance | decimal string, 1 to 96 characters | yes | Exact base-10 amount in the engagement reporting currency. |
account.priorYearBalance | nullable decimal string, 1 to 96 characters | yes | |
account.changeStatus | one of new, removed, significant_increase, significant_decrease, minor_change, unchanged, unknown | yes | |
projection | object | yes | |
projection.postedBookAdjustmentsIncluded | boolean, always true | yes | |
projection.blockedBookAdjustmentsIncluded | boolean, always true | yes | |
projection.workpaperTaxAdjustmentSourcesIncluded | boolean, always true | yes | |
projection.unrelatedBookAdjustmentLinesIncluded | boolean, always false | yes | |
projection.workpaperAmountsAllocatedToAccount | boolean, always false | yes | |
projection.schedule1ImpactEvaluated | boolean, always false | yes | |
projection.computationEvaluated | boolean, always false | yes | |
projection.readinessEvaluated | boolean, always false | yes | |
projection.storageMetadataIncluded | boolean, always false | yes | |
postedBookAdjustmentTotal | decimal string, 1 to 96 characters | yes | Exact base-10 amount in the engagement reporting currency. |
adjustedBookBalance | decimal string, 1 to 96 characters | yes | Exact base-10 amount in the engagement reporting currency. |
bookAdjustments | array of objects, up to 5000 items | yes | |
bookAdjustments[].kind | string, always "book_aje" | yes | |
bookAdjustments[].id | string, 1 to 128 characters | yes | |
bookAdjustments[].number | integer, at least 1 | yes | |
bookAdjustments[].name | string, up to 512 characters | yes | |
bookAdjustments[].description | string, up to 4000 characters | yes | |
bookAdjustments[].entryType | one of adjusting, reclassifying, tax_provision, potential | yes | |
bookAdjustments[].source | one of preparer, client | yes | |
bookAdjustments[].entryDate | nullable string (date) | yes | |
bookAdjustments[].recurring | boolean | yes | |
bookAdjustments[].postingStatus | one of posted, blocked, excluded | yes | |
bookAdjustments[].blockReason | nullable one of unbalanced, unlinked_account | yes | |
bookAdjustments[].totalDebits | decimal string, 1 to 96 characters | yes | Exact base-10 amount in the engagement reporting currency. |
bookAdjustments[].totalCredits | decimal string, 1 to 96 characters | yes | Exact base-10 amount in the engagement reporting currency. |
bookAdjustments[].accountEffect | nullable decimal string, 1 to 96 characters | yes | |
bookAdjustments[].requestedAccountLines | array of objects, up to 2000 items | yes | |
bookAdjustments[].requestedAccountLines[].id | string, 1 to 128 characters | yes | |
bookAdjustments[].requestedAccountLines[].type | one of debit, credit | yes | |
bookAdjustments[].requestedAccountLines[].accountId | string, 1 to 128 characters | yes | |
bookAdjustments[].requestedAccountLines[].accountCode | nullable string, up to 128 characters | yes | |
bookAdjustments[].requestedAccountLines[].accountName | string, up to 512 characters | yes | |
bookAdjustments[].requestedAccountLines[].amount | decimal string, 1 to 96 characters | yes | Exact base-10 amount in the engagement reporting currency. |
workpaperTaxAdjustments | array of objects, up to 2000 items | yes | |
workpaperTaxAdjustments[].kind | string, always "workpaper_tax_adjustment" | yes | |
workpaperTaxAdjustments[].workpaperId | string (uuid) | yes | |
workpaperTaxAdjustments[].templateId | nullable string, up to 256 characters | yes | |
workpaperTaxAdjustments[].displayName | nullable string, up to 512 characters | yes | |
workpaperTaxAdjustments[].version | integer, at least 1 | yes | |
workpaperTaxAdjustments[].lifecycleStatus | string, 1 to 64 characters | yes | |
workpaperTaxAdjustments[].tieOutStatus | nullable one of matched, difference, pending, incomplete | yes | |
workpaperTaxAdjustments[].adjustmentAmount | nullable decimal string, 1 to 96 characters | yes | |
workpaperTaxAdjustments[].adjustmentType | nullable one of addition, deduction | yes | |
workpaperTaxAdjustments[].adjustmentStatus | string, 1 to 128 characters | yes | |
workpaperTaxAdjustments[].legacyStatusDefaulted | boolean | yes | |
workpaperTaxAdjustments[].requiresManualReview | boolean | yes | |
workpaperTaxAdjustments[].linkedAccountCount | integer, at least 1 | yes | |
workpaperTaxAdjustments[].linkedAccountIds | array of strings, 1 to 20000 items | yes | |
workpaperTaxAdjustments[].allocationBasis | string, always "workpaper_total_not_account_allocated" | yes | |
workpaperTaxAdjustments[].schedule1ImpactEvaluated | boolean, always false | yes |
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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
engagement_id | path | string (uuid) | yes |
Request body
Targets to compute from an engagement's saved data, named cells replaced.
| Field | Type | Required | Description |
|---|---|---|---|
compute | array of strings, 1 to 100 items | yes | Schedule/result keys to compute; dependencies run automatically. |
inputs | object | no | Input 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.* | any | no | Members 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
| Field | Type | Always present | Description |
|---|---|---|---|
data | object | yes | One deterministic computation over an engagement's saved inputs. |
data.engagementId | string (uuid) | yes | |
data.sourceStateSha256 | string | yes | Lineage 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.appliedOverrides | array of strings | yes | The input cells this request replaced, in sorted order. Every other cell came from the engagement's saved inputs. |
data.results | object | yes | Engine output for the requested targets and their automatic dependencies. It is a computation, not a filing verdict: readiness is not evaluated here. |
data.results.* | any | no | The target's output cells; see the computation reference. |
computeVersion | string | yes | |
engineSchemaVersion | string | yes | |
ratesVersion | string | yes | |
timestamp | string (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
| Field | Type | Always present | Description |
|---|---|---|---|
data | object | yes | |
data.batchTargets | array of strings | yes | |
data.batchDependencies | map of array of strings | yes | |
data.batchDependencies.{key} | array of strings | per key | |
data.rolloverTargets | array of strings | yes |
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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
target_id | path | string, 1 to 64 characters, matching ^[a-z][a-z0-9_-]*$ | yes | Batch 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
| Field | Type | Always present | Description |
|---|---|---|---|
data | object | yes | The cells one computation target accepts and returns. |
data.id | string | yes | |
data.kind | one of batch, rollover | yes | |
data.program | nullable string | no | |
data.jurisdiction | nullable string | no | |
data.status | nullable string | no | Contract lifecycle status of the target profile. It is not a filing, CRA-acceptance, or tax-semantics determination. |
data.supportedTaxYears | nullable array of objects | no | Inclusive taxation-year windows for schedule targets; null where a year window does not apply, as for rollover targets. |
data.supportedTaxYears[].first | integer | when supportedTaxYears is set | |
data.supportedTaxYears[].last | nullable integer | when supportedTaxYears is set | Last supported taxation year; null means open-ended. |
data.contract | nullable object | no | The exact selector to send as payloadContract to validate a request against this target's pinned schema pair. |
data.contract.boundaryProfileId | string, 1 to 128 characters, matching ^[a-z][a-z0-9_.-]*$ | when contract is set | Exact strict computation boundary profile identifier. |
data.contract.payloadSchemaVersion | string, up to 64 characters, matching ^[0-9]+\.[0-9]+\.[0-9]+$ | when contract is set | Exact semantic version of the target payload schema pair. |
data.inputs | array of objects | yes | |
data.inputs[].path | string | yes | Dotted path of this cell inside the request's inputs object; a [] segment addresses the elements of an array. |
data.inputs[].types | array of strings | yes | Every JSON type the boundary admits at this position. |
data.inputs[].required | boolean | yes | Whether the strict payload contract requires this cell. On the default boundary only the cells flagged requiredOnDefaultBoundary are required. |
data.inputs[].requiredOnDefaultBoundary | boolean | yes | Whether 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[].strictPinned | boolean | yes | Whether 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[].* | any | no | Members not listed here. |
data.outputs | array of objects | yes | |
data.outputs[].path | string | yes | Dotted path of this cell inside the target's result object; a [] segment addresses the elements of an array. |
data.outputs[].types | array of strings | yes | Every JSON type this result position can carry. |
data.outputs[].* | any | no | Members not listed here. |
data.exampleInput | nullable object | no | The target's executed, admission-checked golden request body: the value a caller sends as inputs. |
data.exampleInput.* | any | no | Members not listed here. |
data.dependencies | nullable array of strings | no | Batch 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.
| Field | Type | Required | Description |
|---|---|---|---|
compute | array of strings, 1 to 100 items | yes | Schedule/result keys to compute; dependencies run automatically. |
inputs | object | no | Canonical 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.* | any | no | Members not listed here. |
vendorInput | object | no | Optional 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.vendor | one of taxcycle, taxprep | when vendorInput is set | Vendor vocabulary used by every key in cells. |
vendorInput.cells | object | when vendorInput is set | Exact, 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.* | any | no | Members not listed here. |
payloadContract | object | no | Optional exact strict target contract. Omit this property to use the published legacy computation boundary; null is not valid. |
payloadContract.boundaryProfileId | string, 1 to 128 characters, matching ^[a-z][a-z0-9_.-]*$ | when payloadContract is set | Exact strict computation boundary profile identifier. |
payloadContract.payloadSchemaVersion | string, up to 64 characters, matching ^[0-9]+\.[0-9]+\.[0-9]+$ | when payloadContract is set | Exact semantic version of the target payload schema pair. |
handoff | object | no | Optional 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.vendor | one of taxcycle, taxprep, ifirm | when handoff is set | Receiving 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.format | one of json, file, gfi | when handoff is set | Container 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.language | one of en, fr | when handoff is set | Taxprep 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.corporationName | string, 1 to 200 characters | when handoff is set | Corporation name used to identify a format 'gfi' artifact. Optional on the selector, but format 'gfi' refuses when absent. |
handoff.businessNumber | string, 9 to 32 characters | when handoff is set | Corporation 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
| Field | Type | Always present | Description |
|---|---|---|---|
data | object | yes | Computed 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.results | map of object | no | |
data.results.{key} | object | per key | |
data.results.{key}.ready | boolean | per key | |
data.results.{key}.provisional | boolean | per key | |
data.results.{key}.warnings | array of any | per key | |
data.results.{key}.* | any | no | The target's output cells; see the computation reference. |
data.result | object | no | |
data.result.ready | boolean | when result is set | |
data.result.provisional | boolean | when result is set | |
data.result.warnings | array of any | when result is set | |
data.result.* | any | no | The target's output cells; see the computation reference. |
data.handoff | object | no | |
data.handoff.blocked | nullable object | when handoff is set | |
data.handoff.warnings | array of any | when handoff is set | |
data.handoff.* | any | no | Members not listed here. |
data.vendorInput | object | no | Mapping provenance for accepted vendor cells; present only when vendorInput was submitted. Values are never echoed. |
data.vendorInput.vendor | one of taxcycle, taxprep | when vendorInput is set | |
data.vendorInput.mappingTableVersion | string | when vendorInput is set | |
data.vendorInput.vendorEdition | nullable string | when vendorInput is set | |
data.vendorInput.fieldMapVersion | string | when vendorInput is set | |
data.vendorInput.applied | array of objects | when vendorInput is set | |
data.vendorInput.applied[].cell | string | when vendorInput is set | |
data.vendorInput.applied[].schedule | string | when vendorInput is set | |
data.vendorInput.applied[].filemarkConcept | string | when vendorInput is set | |
data.vendorInput.applied[].inputPath | string | when vendorInput is set | |
data.vendorInput.applied[].cardinality | string, always "one_to_one" | when vendorInput is set | |
data.readiness | object | no | |
data.readiness.ready | boolean | when readiness is set | |
data.readiness.* | any | no | Members not listed here. |
data.* | any | no | Members not listed here. |
computeVersion | string | yes | |
engineSchemaVersion | string | yes | |
ratesVersion | string | yes | Content 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. |
timestamp | string (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
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
target | path | string | yes |
Request body
Inputs for one rollover, reorganization, or screening engine.
| Field | Type | Required | Description |
|---|---|---|---|
inputs | object | no | Canonical 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.* | any | no | Members not listed here. |
payloadContract | object | no | Optional exact strict target contract. Omit this property to use the published legacy computation boundary; null is not valid. |
payloadContract.boundaryProfileId | string, 1 to 128 characters, matching ^[a-z][a-z0-9_.-]*$ | when payloadContract is set | Exact strict computation boundary profile identifier. |
payloadContract.payloadSchemaVersion | string, up to 64 characters, matching ^[0-9]+\.[0-9]+\.[0-9]+$ | when payloadContract is set | Exact 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
| Field | Type | Always present | Description |
|---|---|---|---|
data | object | yes | Computed 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.results | map of object | no | |
data.results.{key} | object | per key | |
data.results.{key}.ready | boolean | per key | |
data.results.{key}.provisional | boolean | per key | |
data.results.{key}.warnings | array of any | per key | |
data.results.{key}.* | any | no | The target's output cells; see the computation reference. |
data.result | object | no | |
data.result.ready | boolean | when result is set | |
data.result.provisional | boolean | when result is set | |
data.result.warnings | array of any | when result is set | |
data.result.* | any | no | The target's output cells; see the computation reference. |
data.handoff | object | no | |
data.handoff.blocked | nullable object | when handoff is set | |
data.handoff.warnings | array of any | when handoff is set | |
data.handoff.* | any | no | Members not listed here. |
data.vendorInput | object | no | Mapping provenance for accepted vendor cells; present only when vendorInput was submitted. Values are never echoed. |
data.vendorInput.vendor | one of taxcycle, taxprep | when vendorInput is set | |
data.vendorInput.mappingTableVersion | string | when vendorInput is set | |
data.vendorInput.vendorEdition | nullable string | when vendorInput is set | |
data.vendorInput.fieldMapVersion | string | when vendorInput is set | |
data.vendorInput.applied | array of objects | when vendorInput is set | |
data.vendorInput.applied[].cell | string | when vendorInput is set | |
data.vendorInput.applied[].schedule | string | when vendorInput is set | |
data.vendorInput.applied[].filemarkConcept | string | when vendorInput is set | |
data.vendorInput.applied[].inputPath | string | when vendorInput is set | |
data.vendorInput.applied[].cardinality | string, always "one_to_one" | when vendorInput is set | |
data.readiness | object | no | |
data.readiness.ready | boolean | when readiness is set | |
data.readiness.* | any | no | Members not listed here. |
data.* | any | no | Members not listed here. |
computeVersion | string | yes | |
engineSchemaVersion | string | yes | |
ratesVersion | string | yes | Content 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. |
timestamp | string (date-time) | yes |
Errors
The shared codes only; see error codes.