Run computations
POST /api/v1/computations/batch and POST /api/v1/computations/rollovers/{target} run only from the inputs you submit; neither takes an engagement ID. To compute from an engagement's stored inputs instead, see Compute over saved data. GET /api/v1/computations returns the available targets: the batch targets, their dependency graph, and the rollover targets. The computation reference lists each target's input and output cells, their accepted values, which cells are always required, and an example request.
Run a batch computation
curl --request POST https://api.filemark.ca/api/v1/computations/batch \
--header "Authorization: Bearer $FILEMARK_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"compute": [
"schedule3"
],
"inputs": {
"taxYear": 2025,
"workpapers": [
{
"id": "wp-dividends-target",
"templateId": "dividends",
"linkedAccountIds": [],
"adjustmentStatus": "ok",
"customName": "Cedar Ridge 2025 capital dividend",
"rows": [
{
"payerName": "Cedar Ridge Manufacturing Inc.",
"amountCY": 80000,
"isConnected": "no",
"dividendType": "Capital Dividend",
"direction": "paid",
"dividendSource": "canadian_taxable",
"denial112": false,
"foreignCurrency": "CAD"
}
],
"sectionRows": {},
"assumption": "Caller-supplied facts only; no CDA balance, election, recipient/share, payment, or filing verification"
}
]
}
}'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": [
"schedule3",
],
"inputs": {
"taxYear": 2025,
"workpapers": [
{
"id": "wp-dividends-target",
"templateId": "dividends",
"linkedAccountIds": [],
"adjustmentStatus": "ok",
"customName": "Cedar Ridge 2025 capital dividend",
"rows": [
{
"payerName": "Cedar Ridge Manufacturing Inc.",
"amountCY": 80000,
"isConnected": "no",
"dividendType": "Capital Dividend",
"direction": "paid",
"dividendSource": "canadian_taxable",
"denial112": False,
"foreignCurrency": "CAD",
},
],
"sectionRows": {},
"assumption": "Caller-supplied facts only; no CDA balance, election, recipient/share, payment, or filing verification",
},
],
},
},
)
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": [
"schedule3"
],
"inputs": {
"taxYear": 2025,
"workpapers": [
{
"id": "wp-dividends-target",
"templateId": "dividends",
"linkedAccountIds": [],
"adjustmentStatus": "ok",
"customName": "Cedar Ridge 2025 capital dividend",
"rows": [
{
"payerName": "Cedar Ridge Manufacturing Inc.",
"amountCY": 80000,
"isConnected": "no",
"dividendType": "Capital Dividend",
"direction": "paid",
"dividendSource": "canadian_taxable",
"denial112": false,
"foreignCurrency": "CAD"
}
],
"sectionRows": {},
"assumption": "Caller-supplied facts only; no CDA balance, election, recipient/share, payment, or filing verification"
}
]
}
}),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());compute names 1 to 100 targets; their dependencies run automatically. inputs holds the engine inputs, and a four-digit inputs.taxYear is required. The optional payloadContract and handoff selectors reject null; omit the property instead. Every field is listed under Compute tax schedules.
Responses share one envelope: results keyed by target under data.results (a rollover returns data.result), plus computeVersion, engineSchemaVersion, ratesVersion, and timestamp. Each result carries ready and provisional booleans, a warnings array, and the target's output cells. Two responses with the same computeVersion and ratesVersion were computed on identical engine code and identical rate tables.
Every inputs member is checked against the published input cells of the requested targets and of the dependencies that run automatically: the member must be one of those cells and must use its published JSON type. A misspelled or unpublished member fails the call with a 400 whose error.details names each failing cell; see validation details. A published cell set to null counts as unanswered, and the engine reports what that leaves unresolved.
This default boundary checks cell names and JSON types, not values, with one exception: a few rollover facts must be answered, because the engine will not choose a statutory branch for you. For per-value validation, pin a strict contract. Structural bounds apply either way: at most 500 elements in any array (413), at most 12 levels of nesting (400), and no numeric value above 1e15 in absolute terms, NaN, or Infinity (400). A target name that is not in the catalog is a 400 that names it.
Get handoff cells
Add the handoff selector to also return the computed schedule cells as the receiving tax software's import identifiers and encoded values:
curl --request POST https://api.filemark.ca/api/v1/computations/batch \
--header "Authorization: Bearer $FILEMARK_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"compute": [
"schedule8"
],
"inputs": {
"taxYear": 2025,
"fiscalStart": "2025-01-01",
"fiscalEnd": "2025-12-31",
"isCCPC": true,
"daysInYear": 365,
"pyUCCPools": [
{
"ccaClass": "8",
"closingUCC": 0
}
],
"assetData": [],
"dispositions": [],
"schedule8AdjustmentCoverage": {
"schemaVersion": 2,
"reviewed": true,
"reviewedAt": "2026-07-19T12:00:00Z",
"column205AdjustmentsApplicable": false,
"column221AssistanceAfterDispositionApplicable": false,
"column222RepaymentsAfterDispositionApplicable": false,
"rentalPropertySeparateClassApplicable": false,
"purposeBuiltRentalPropertyRulesApplicable": false,
"rentalIncomeCcaLimitApplicable": false,
"leasingPropertyRulesApplicable": false,
"specifiedLeasingPropertyRulesApplicable": false,
"affiliatedPersonStopLossApplicable": false,
"reg1101_5qElectionApplies": false,
"multipleClass10_1VehiclesPresent": false,
"otherPrescribedSeparateClassRuleApplies": false,
"specialDispositionRolloverOrDeferralApplies": false,
"class14_1TransitionalOpeningBalanceApplicable": false,
"specifiedEnergyPropertyRulesApplicable": false,
"class1NrbAdditionalAllowanceEligible": false,
"class1UnmodelledAdditionalAllowanceApplies": false,
"class12ParagraphHalfYearExclusionApplies": false,
"diepEligibilityAndAllocationConfirmed": false,
"capitalGainRoutingComplete": false
},
"t2Jacket": {
"filingStatus": {
"firstYearAfterIncorporation": false,
"firstYearAfterAmalgamation": false,
"subsidiaryWindupS88": false
}
}
},
"handoff": {
"vendor": "taxprep"
}
}'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": [
"schedule8",
],
"inputs": {
"taxYear": 2025,
"fiscalStart": "2025-01-01",
"fiscalEnd": "2025-12-31",
"isCCPC": True,
"daysInYear": 365,
"pyUCCPools": [
{
"ccaClass": "8",
"closingUCC": 0,
},
],
"assetData": [],
"dispositions": [],
"schedule8AdjustmentCoverage": {
"schemaVersion": 2,
"reviewed": True,
"reviewedAt": "2026-07-19T12:00:00Z",
"column205AdjustmentsApplicable": False,
"column221AssistanceAfterDispositionApplicable": False,
"column222RepaymentsAfterDispositionApplicable": False,
"rentalPropertySeparateClassApplicable": False,
"purposeBuiltRentalPropertyRulesApplicable": False,
"rentalIncomeCcaLimitApplicable": False,
"leasingPropertyRulesApplicable": False,
"specifiedLeasingPropertyRulesApplicable": False,
"affiliatedPersonStopLossApplicable": False,
"reg1101_5qElectionApplies": False,
"multipleClass10_1VehiclesPresent": False,
"otherPrescribedSeparateClassRuleApplies": False,
"specialDispositionRolloverOrDeferralApplies": False,
"class14_1TransitionalOpeningBalanceApplicable": False,
"specifiedEnergyPropertyRulesApplicable": False,
"class1NrbAdditionalAllowanceEligible": False,
"class1UnmodelledAdditionalAllowanceApplies": False,
"class12ParagraphHalfYearExclusionApplies": False,
"diepEligibilityAndAllocationConfirmed": False,
"capitalGainRoutingComplete": False,
},
"t2Jacket": {
"filingStatus": {
"firstYearAfterIncorporation": False,
"firstYearAfterAmalgamation": False,
"subsidiaryWindupS88": False,
},
},
},
"handoff": {
"vendor": "taxprep",
},
},
)
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": [
"schedule8"
],
"inputs": {
"taxYear": 2025,
"fiscalStart": "2025-01-01",
"fiscalEnd": "2025-12-31",
"isCCPC": true,
"daysInYear": 365,
"pyUCCPools": [
{
"ccaClass": "8",
"closingUCC": 0
}
],
"assetData": [],
"dispositions": [],
"schedule8AdjustmentCoverage": {
"schemaVersion": 2,
"reviewed": true,
"reviewedAt": "2026-07-19T12:00:00Z",
"column205AdjustmentsApplicable": false,
"column221AssistanceAfterDispositionApplicable": false,
"column222RepaymentsAfterDispositionApplicable": false,
"rentalPropertySeparateClassApplicable": false,
"purposeBuiltRentalPropertyRulesApplicable": false,
"rentalIncomeCcaLimitApplicable": false,
"leasingPropertyRulesApplicable": false,
"specifiedLeasingPropertyRulesApplicable": false,
"affiliatedPersonStopLossApplicable": false,
"reg1101_5qElectionApplies": false,
"multipleClass10_1VehiclesPresent": false,
"otherPrescribedSeparateClassRuleApplies": false,
"specialDispositionRolloverOrDeferralApplies": false,
"class14_1TransitionalOpeningBalanceApplicable": false,
"specifiedEnergyPropertyRulesApplicable": false,
"class1NrbAdditionalAllowanceEligible": false,
"class1UnmodelledAdditionalAllowanceApplies": false,
"class12ParagraphHalfYearExclusionApplies": false,
"diepEligibilityAndAllocationConfirmed": false,
"capitalGainRoutingComplete": false
},
"t2Jacket": {
"filingStatus": {
"firstYearAfterIncorporation": false,
"firstYearAfterAmalgamation": false,
"subsidiaryWindupS88": false
}
}
},
"handoff": {
"vendor": "taxprep"
}
}),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());data.handoff appears beside data.results. Its values match the handoff files the Filemark app exports from the same computation, byte for byte:
{
"vendor": "taxprep",
"mappingTableVersion": "0.4.8",
"vendorEdition": "T2 Taxprep 2024 v.2",
"cells": [
{ "cellId": "CCACat.FD08C[1].FED.Ttw08cA5", "value": "50000" },
{ "cellId": "CCACat.FD08C[1].FED.Ttw08cA1", "value": "8" }
],
"blocked": null,
"warnings": []
}| Field | Meaning |
|---|---|
vendor | "taxcycle", "taxprep", or "ifirm", echoing the selector. |
mappingTableVersion | Version of the Filemark mapping table the identifiers came from. |
vendorEdition | The build the identifiers were mapped against. Confirm your install matches it before importing. |
cells | For taxprep: .csv cell IDs. For ifirm: cells/setdata cell paths. |
forms | For taxcycle, replacing cells: import field codes grouped per form ([{form, cells}]). A tableClear entry reproduces the product's repeating-table clear row. |
warnings | One {code, message} per computed cell the selected product cannot carry. Branch on code; message is prose. |
blocked | null when the projection was built. Otherwise an object whose reason says why Filemark would refuse the equivalent handoff export or could not build the selected product's payload; it may also carry a code, an action, and the issues behind the refusal. data.results is unaffected either way. |
The T2 jacket and Schedule 141 are not batch targets, so their cells never appear here. handoff and payloadContract can be sent together.
Get the import file
Send the same request with format added to the handoff selector to get the receiving tax software's import file instead of the cell list:
"handoff": {
"vendor": "taxprep",
"format": "file"
}In the response, data.handoff.files replaces cells/forms; warnings, blocked, vendorEdition, and mappingTableVersion are unchanged. Every entry's content is base64, the .csv included.
{
"vendor": "taxprep",
"mappingTableVersion": "0.4.8",
"vendorEdition": "T2 Taxprep 2024 v.2",
"files": [
{
"filename": "filemark_taxprep.csv",
"mediaType": "text/csv; charset=utf-8",
"encoding": "base64",
"content": "W0ZpbGVtYXJrfDB8MF0NCg…"
}
],
"blocked": null,
"warnings": []
}format | Result |
|---|---|
omitted, or "json" | cells or forms, exactly as above. |
"file" | files. For taxprep and ifirm: one .csv. For taxcycle: one .xlsx per form. |
Pin a strict contract
Add payloadContract to pin one target to a strict contract. Its value is the boundaryProfileId and payloadSchemaVersion pair published for that target in the computation reference.
- It names exactly one direct target. A value with no published contract is a
400. - Inputs are validated against that version's input schema before execution; a mismatch is a
400and nothing runs.error.detailsnames each failing cell and the constraint it violated; see validation details. - The computed result is validated against that version's output schema afterwards. If the contract admitted your request but cannot express the answer, the call fails with a
422whoseerror.codeisresult_not_representableand no result is returned: choose a version that covers this branch, or supply inputs that keep the computation on a declared one. Engine faults on the same stage remain500. - A pinned version is a floor, not a freeze. Within one
payloadSchemaVersionthe output can gain keys, an output enum can gain members, bounds can widen, and new optional inputs can appear; removing an output key, changing an output type, narrowing an enum, or tightening an input requires a new version. Tolerate unknown output keys and enum members.
Run a rollover
One rollover, reorganization, or screening target from the catalog:
curl --request POST https://api.filemark.ca/api/v1/computations/rollovers/section-86 \
--header "Authorization: Bearer $FILEMARK_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"inputs": {
"old_shares": {
"acb": 100000,
"puc": 80000,
"fmv": 150000,
"isCapitalProperty": true,
"allSharesOfClassDisposed": true,
"outlaysAndExpenses": 0,
"priorS53_2_g1DeductionsAmount": null,
"priorS53_2_g1Deductions": false
},
"new_shares": [
{
"label": "Cedar Ridge Holdings preferred",
"fmv": 90000,
"legalStatedCapital": 60000
},
{
"label": "Cedar Ridge Holdings common",
"fmv": 50000,
"legalStatedCapital": 50000
}
],
"boot": {
"fmv": 10000
},
"party": {
"s85ElectionFiled": false,
"inCourseOfReorganizationOfCapital": true,
"isRelatedReorganization": false,
"giftToRelatedPerson": 0
}
}
}'import os
import requests
FILEMARK_ACCESS_TOKEN = os.environ["FILEMARK_ACCESS_TOKEN"]
response = requests.post(
"https://api.filemark.ca/api/v1/computations/rollovers/section-86",
headers={
"Authorization": f"Bearer {FILEMARK_ACCESS_TOKEN}",
},
json={
"inputs": {
"old_shares": {
"acb": 100000,
"puc": 80000,
"fmv": 150000,
"isCapitalProperty": True,
"allSharesOfClassDisposed": True,
"outlaysAndExpenses": 0,
"priorS53_2_g1DeductionsAmount": None,
"priorS53_2_g1Deductions": False,
},
"new_shares": [
{
"label": "Cedar Ridge Holdings preferred",
"fmv": 90000,
"legalStatedCapital": 60000,
},
{
"label": "Cedar Ridge Holdings common",
"fmv": 50000,
"legalStatedCapital": 50000,
},
],
"boot": {
"fmv": 10000,
},
"party": {
"s85ElectionFiled": False,
"inCourseOfReorganizationOfCapital": True,
"isRelatedReorganization": False,
"giftToRelatedPerson": 0,
},
},
},
)
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-86", {
method: "POST",
headers: {
Authorization: `Bearer ${FILEMARK_ACCESS_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"inputs": {
"old_shares": {
"acb": 100000,
"puc": 80000,
"fmv": 150000,
"isCapitalProperty": true,
"allSharesOfClassDisposed": true,
"outlaysAndExpenses": 0,
"priorS53_2_g1DeductionsAmount": null,
"priorS53_2_g1Deductions": false
},
"new_shares": [
{
"label": "Cedar Ridge Holdings preferred",
"fmv": 90000,
"legalStatedCapital": 60000
},
{
"label": "Cedar Ridge Holdings common",
"fmv": 50000,
"legalStatedCapital": 50000
}
],
"boot": {
"fmv": 10000
},
"party": {
"s85ElectionFiled": false,
"inCourseOfReorganizationOfCapital": true,
"isRelatedReorganization": false,
"giftToRelatedPerson": 0
}
}
}),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());Compute over saved data
POST /api/v1/engagements/{engagement_id}/computations/scenario computes from an engagement's saved inputs and replaces only the cells you name. It needs both tax-data:read and tax:compute.
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": {}
}'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": {},
},
)
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": {}
}),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());Send inputs: {} to compute the engagement as saved. A member of inputs replaces its whole top-level cell rather than merging into it, and null means unanswered. The cells that identify the taxation period (taxYear, taxYearId, currentYear, daysInYear, fiscalStart, fiscalEnd, priorTaxYearStart, priorTaxYearEnd, pinnedFormRevisions) and the server-authored filing-lineage cells cannot be replaced; naming one is a 400 that lists each refused cell in error.details. To compute a different period, send a full payload to the batch endpoint instead.
data.appliedOverrides lists the cells this request replaced and data.sourceStateSha256 identifies the saved state they were applied to, so two responses with the same hash are comparable. Nothing is persisted and saved inputs are never returned. Field-level detail is under Compute an engagement's saved state with cells replaced.