DocMake
The PDF DocMake makes from the Preventive Maintenance Checklist template

The first page of the document DocMake makes from the sample values on this page.

Operations

Preventive Maintenance Checklist

A preventive maintenance checklist is a scheduled visit written down in advance. The asset, the interval and the task list are decided before anyone travels, which is what separates it from a reactive callout where the work is whatever the fault turns out to be. The engineer arrives with the list already on the tablet, works through it, and the completed record is the evidence that the interval was actually served rather than skipped in a busy month.

Tick boxes on their own are close to worthless. A checklist that only records that a belt was checked cannot tell anyone whether the belt is getting worse, whereas one that records belt deflection in millimetres against the manufacturer limit can. Readings are what make maintenance predictive: refrigerant superheat, filter differential pressure, bearing temperature, insulation resistance and run hours all trend, and the trend is what moves a component from the quarterly list to the next shutdown before it fails on a Friday afternoon.

Grouping tasks by system rather than by trade keeps the visit honest. An air handling unit visit that runs filters, fans, coils, dampers, controls and drainage as separate blocks makes it obvious when a whole block was skipped, which a flat list of forty lines does not. Each task carries a result and, where it failed, a defect reference, because the point of the visit is not the ticks but the small number of defects it generates and who now owns them.

The commercial side sits in the same document. Contract reference, interval, tasks deferred and the reason, consumables used against the contract allowance, and the next due date are what a facilities manager reads first. Rendering the checklist from JSON lets the maintenance system emit the correct task list for each asset class, fill the readings from the engineer's form, and return one branded PDF per visit, which for a contractor running two hundred planned visits a month is two hundred documents from one template.

Blanks to fill

visit_reference Visit reference
visit_date Visit date
contract_reference Contract
visit_number Visit in the schedule
service_provider Service provider
customer Customer
site_name Site
site_address Site address
asset_description Asset
asset_id Asset tag
asset_location Location
manufacturer Manufacturer
model Model
serial_number Serial number
commissioned In service since
maintenance_interval Interval
previous_visit Previous visit
engineer Engineer
engineer_qualification Qualification held
time_on_site Time on site
isolation_note Isolation and safe system of work
asset_state_on_arrival Asset state on arrival
tasks_deferred Tasks deferred
deferral_reason Reason for deferral
asset_state_on_departure Asset state on departure
overall_condition Overall condition
next_visit_due Next visit due
engineer_declaration Engineer declaration
witnessed_by Witnessed by
witnessed_date Witnessed
company_name Company
tasks[] One per item, so a row is added for every item in the list
readings[] One per item, so a row is added for every item in the list
consumables[] One per item, so a row is added for every item in the list
defects[] One per item, so a row is added for every item in the list

The data behind the preview

This is the exact JSON that produced the document above. Change the values, POST them to the API, and you get your version back as DOCX or PDF. Lists grow and shrink with your data; the layout adapts.

  1. 01 Sign up free and duplicate this template into your workspace.
  2. 02 Adjust the wording and branding in the visual editor.
  3. 03 Fill it in the app, share it as a form link, or call the API.
sample-data.json
{
  "company_name": "Kestrel M&E Ltd",
  "visit_reference": "PPM-2026-1194",
  "contract_reference": "MC-2024-0031, planned maintenance, mechanical services",
  "service_provider": "Kestrel M&E Ltd",
  "customer": "Brookmill Estates Management Ltd",
  "site_name": "Brookmill Business Park, block C",
  "site_address": "Brookmill Way, Bristol BS16 1QD, United Kingdom",
  "asset_id": "CH-01",
  "asset_description": "Air cooled chiller, 320 kW nominal cooling duty, two circuits, scroll compressors",
  "asset_location": "Roof plant deck, north end",
  "manufacturer": "Alderfen Air Systems",
  "model": "ACC-320-2S",
  "serial_number": "ACC-320-2019-0733",
  "commissioned": "May 2019",
  "maintenance_interval": "Quarterly, with the annual tasks folded into the summer visit",
  "visit_number": "Visit 3 of 4 in the 2026 schedule",
  "visit_date": "October 8, 2026",
  "previous_visit": "PPM-2026-0908, July 9, 2026",
  "engineer": "Tom Beddoe",
  "engineer_qualification": "Refrigerant handling category I, in date to March 2029",
  "time_on_site": "08:40 to 13:05",
  "isolation_note": "Local isolator locked off under padlock 22 with the key held by the engineer for the electrical checks. Chiller returned to automatic control before the isolation was removed. Roof access permit RA-BM-2026-118 issued by the site team on arrival.",
  "asset_state_on_arrival": "Running on circuit 1 only. Circuit 2 locked out on a low pressure alarm raised overnight on October 6 and not reset by site.",
  "tasks": [
    {
      "system": "General",
      "description": "Visual check of the frame, panels and guards",
      "result": "Pass",
      "note": "Two panel fasteners replaced from van stock"
    },
    {
      "system": "General",
      "description": "Read the unit log and the alarm history",
      "result": "Pass",
      "note": "Four low pressure alarms on circuit 2 since September 18"
    },
    {
      "system": "Condenser",
      "description": "Clean the coils and check the fins",
      "result": "Pass",
      "note": "Washed, light debris off the car park trees"
    },
    {
      "system": "Condenser",
      "description": "Check fan operation and bearings",
      "result": "Pass",
      "note": "All six fans run, no bearing noise"
    },
    {
      "system": "Refrigeration",
      "description": "Leak check at joints, valves and ports",
      "result": "Fail",
      "note": "Leak at the circuit 2 liquid line port, defect DEF-2026-0417"
    },
    {
      "system": "Refrigeration",
      "description": "Record pressures, superheat and subcooling",
      "result": "Pass",
      "note": "Circuit 2 superheat high, in line with the leak"
    },
    {
      "system": "Electrical",
      "description": "Thermal check of the panel under load",
      "result": "Pass",
      "note": "No hot spots, highest termination 41 C"
    },
    {
      "system": "Controls",
      "description": "Check setpoints, sensors and safety cut outs",
      "result": "Pass",
      "note": "Leaving water sensor 0.3 C out, inside tolerance"
    },
    {
      "system": "Water side",
      "description": "Check the strainer and the flow switch",
      "result": "Pass",
      "note": "Strainer cleaned, light magnetite"
    },
    {
      "system": "Water side",
      "description": "Test glycol strength and inhibitor level",
      "result": "Fail",
      "note": "Glycol at 22 percent against 30, defect DEF-2026-0418"
    }
  ],
  "readings": [
    {
      "parameter": "Circuit 1 suction pressure",
      "value": "5.9 bar",
      "limit": "5.5 to 6.5 bar at this ambient",
      "previous": "6.1 bar",
      "verdict": "Pass"
    },
    {
      "parameter": "Circuit 1 superheat",
      "value": "6.8 K",
      "limit": "5 K to 8 K",
      "previous": "6.5 K",
      "verdict": "Pass"
    },
    {
      "parameter": "Circuit 2 superheat",
      "value": "14.2 K",
      "limit": "5 K to 8 K",
      "previous": "7.9 K",
      "verdict": "Fail"
    },
    {
      "parameter": "Circuit 2 subcooling",
      "value": "1.9 K",
      "limit": "4 K to 7 K",
      "previous": "5.2 K",
      "verdict": "Fail"
    },
    {
      "parameter": "Compressor 1A running current",
      "value": "68 A",
      "limit": "Below 82 A nameplate",
      "previous": "67 A",
      "verdict": "Pass"
    },
    {
      "parameter": "Evaporator pressure drop",
      "value": "42 kPa",
      "limit": "35 kPa to 55 kPa",
      "previous": "40 kPa",
      "verdict": "Pass"
    },
    {
      "parameter": "Glycol concentration",
      "value": "22 percent by volume",
      "limit": "30 percent by volume",
      "previous": "27 percent by volume",
      "verdict": "Fail"
    },
    {
      "parameter": "Leaving chilled water temperature at setpoint",
      "value": "6.4 C",
      "limit": "6.0 C plus or minus 0.5 K",
      "previous": "6.1 C",
      "verdict": "Pass"
    },
    {
      "parameter": "Run hours, circuit 1",
      "value": "31,480 hours",
      "limit": "Trend only",
      "previous": "30,910 hours",
      "verdict": "Recorded"
    },
    {
      "parameter": "Run hours, circuit 2",
      "value": "29,660 hours",
      "limit": "Trend only",
      "previous": "29,455 hours",
      "verdict": "Recorded"
    }
  ],
  "consumables": [
    {
      "item": "Panel fasteners, stainless",
      "quantity": "2",
      "covered_by_contract": "Yes"
    },
    {
      "item": "Schrader valve cores",
      "quantity": "4",
      "covered_by_contract": "Yes"
    },
    {
      "item": "Coil cleaning chemical, non acidic",
      "quantity": "5 litres",
      "covered_by_contract": "Yes"
    },
    {
      "item": "Refrigerant R-32 for top up after repair",
      "quantity": "None added, held until the leak is repaired",
      "covered_by_contract": "No, quoted with the repair"
    }
  ],
  "defects": [
    {
      "reference": "DEF-2026-0417",
      "description": "Refrigerant leak at the circuit 2 liquid line schrader port, confirmed with an electronic detector and bubble solution. The port cap was missing and the core seal is worn rather than damaged. Circuit 2 is undercharged, which explains the overnight low pressure lockouts and the high superheat.",
      "severity": "High, circuit unavailable",
      "action": "Return visit to recover the remaining charge, replace the schrader core and cap, pressure test, evacuate and recharge by weight, then leak check again and log the charge",
      "owner": "Kestrel M&E, quoted separately as it falls outside the planned scope"
    },
    {
      "reference": "DEF-2026-0418",
      "description": "Glycol concentration has fallen from 27 percent to 22 percent across two visits, which suggests dilution from make up water rather than normal loss. The sample was drawn from the drain point and tested twice with the same result. Freeze protection is below the design figure before winter.",
      "severity": "Medium, seasonal",
      "action": "Trace the make up water path and check the fill valve, then correct the concentration by dosing and retest",
      "owner": "Brookmill Estates Management to name the water treatment contractor, Kestrel to retest on the next visit"
    }
  ],
  "tasks_deferred": "Annual compressor vibration survey and the evaporator inspection are scheduled with the summer visit and were not due on this one.",
  "deferral_reason": "Interval based, not deferred by circumstance. No task in the quarterly list was skipped on this visit.",
  "asset_state_on_departure": "Circuit 1 running under automatic control and holding setpoint. Circuit 2 left isolated at the controller with the site team informed, pending the leak repair. Cooling capacity is reduced but the block is served.",
  "overall_condition": "Serviceable with two open defects. For a unit in its eighth season the mechanical condition is good, and both defects are repairable rather than end of life indicators.",
  "next_visit_due": "January 2027, quarterly interval, subject to the leak repair visit happening first",
  "engineer_declaration": "I confirm the tasks marked complete were carried out, the readings are those I measured, and the defects listed are those found on this visit.",
  "witnessed_by": "Hana Duarte, Facilities Coordinator, Brookmill Estates Management Ltd",
  "witnessed_date": "October 8, 2026"
}

Generate this document via the API

One template plus changing data is the whole point. The list of blanks above is the contract, and every new set of values comes back in the same layout: fill it in the app, hand someone a form link, or POST the JSON and get the file straight back.

The request below carries this page's own values, so it runs as soon as the template exists in your workspace. Swap the values for yours and the response is your document.

make-preventive-maintenance-checklist.sh
curl -X POST https://app.docmake.io/api/v1/render \
  -H "Authorization: Bearer $DOCMAKE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  --output preventive-maintenance-checklist.pdf \
  --data-binary @- <<'JSON'
{
  "template_id": "tmpl_your_template_id",
  "format": "pdf",
  "data": {
    "company_name": "Kestrel M&E Ltd",
    "visit_reference": "PPM-2026-1194",
    "contract_reference": "MC-2024-0031, planned maintenance, mechanical services",
    "service_provider": "Kestrel M&E Ltd",
    "customer": "Brookmill Estates Management Ltd",
    "site_name": "Brookmill Business Park, block C",
    "site_address": "Brookmill Way, Bristol BS16 1QD, United Kingdom",
    "asset_id": "CH-01",
    "asset_description": "Air cooled chiller, 320 kW nominal cooling duty, two circuits, scroll compressors",
    "asset_location": "Roof plant deck, north end",
    "manufacturer": "Alderfen Air Systems",
    "model": "ACC-320-2S",
    "serial_number": "ACC-320-2019-0733",
    "commissioned": "May 2019",
    "maintenance_interval": "Quarterly, with the annual tasks folded into the summer visit",
    "visit_number": "Visit 3 of 4 in the 2026 schedule",
    "visit_date": "October 8, 2026",
    "previous_visit": "PPM-2026-0908, July 9, 2026",
    "engineer": "Tom Beddoe",
    "engineer_qualification": "Refrigerant handling category I, in date to March 2029",
    "time_on_site": "08:40 to 13:05",
    "isolation_note": "Local isolator locked off under padlock 22 with the key held by the engineer for the electrical checks. Chiller returned to automatic control before the isolation was removed. Roof access permit RA-BM-2026-118 issued by the site team on arrival.",
    "asset_state_on_arrival": "Running on circuit 1 only. Circuit 2 locked out on a low pressure alarm raised overnight on October 6 and not reset by site.",
    "tasks": [
      {
        "system": "General",
        "description": "Visual check of the frame, panels and guards",
        "result": "Pass",
        "note": "Two panel fasteners replaced from van stock"
      },
      {
        "system": "General",
        "description": "Read the unit log and the alarm history",
        "result": "Pass",
        "note": "Four low pressure alarms on circuit 2 since September 18"
      },
      {
        "system": "Condenser",
        "description": "Clean the coils and check the fins",
        "result": "Pass",
        "note": "Washed, light debris off the car park trees"
      },
      {
        "system": "Condenser",
        "description": "Check fan operation and bearings",
        "result": "Pass",
        "note": "All six fans run, no bearing noise"
      },
      {
        "system": "Refrigeration",
        "description": "Leak check at joints, valves and ports",
        "result": "Fail",
        "note": "Leak at the circuit 2 liquid line port, defect DEF-2026-0417"
      },
      {
        "system": "Refrigeration",
        "description": "Record pressures, superheat and subcooling",
        "result": "Pass",
        "note": "Circuit 2 superheat high, in line with the leak"
      },
      {
        "system": "Electrical",
        "description": "Thermal check of the panel under load",
        "result": "Pass",
        "note": "No hot spots, highest termination 41 C"
      },
      {
        "system": "Controls",
        "description": "Check setpoints, sensors and safety cut outs",
        "result": "Pass",
        "note": "Leaving water sensor 0.3 C out, inside tolerance"
      },
      {
        "system": "Water side",
        "description": "Check the strainer and the flow switch",
        "result": "Pass",
        "note": "Strainer cleaned, light magnetite"
      },
      {
        "system": "Water side",
        "description": "Test glycol strength and inhibitor level",
        "result": "Fail",
        "note": "Glycol at 22 percent against 30, defect DEF-2026-0418"
      }
    ],
    "readings": [
      {
        "parameter": "Circuit 1 suction pressure",
        "value": "5.9 bar",
        "limit": "5.5 to 6.5 bar at this ambient",
        "previous": "6.1 bar",
        "verdict": "Pass"
      },
      {
        "parameter": "Circuit 1 superheat",
        "value": "6.8 K",
        "limit": "5 K to 8 K",
        "previous": "6.5 K",
        "verdict": "Pass"
      },
      {
        "parameter": "Circuit 2 superheat",
        "value": "14.2 K",
        "limit": "5 K to 8 K",
        "previous": "7.9 K",
        "verdict": "Fail"
      },
      {
        "parameter": "Circuit 2 subcooling",
        "value": "1.9 K",
        "limit": "4 K to 7 K",
        "previous": "5.2 K",
        "verdict": "Fail"
      },
      {
        "parameter": "Compressor 1A running current",
        "value": "68 A",
        "limit": "Below 82 A nameplate",
        "previous": "67 A",
        "verdict": "Pass"
      },
      {
        "parameter": "Evaporator pressure drop",
        "value": "42 kPa",
        "limit": "35 kPa to 55 kPa",
        "previous": "40 kPa",
        "verdict": "Pass"
      },
      {
        "parameter": "Glycol concentration",
        "value": "22 percent by volume",
        "limit": "30 percent by volume",
        "previous": "27 percent by volume",
        "verdict": "Fail"
      },
      {
        "parameter": "Leaving chilled water temperature at setpoint",
        "value": "6.4 C",
        "limit": "6.0 C plus or minus 0.5 K",
        "previous": "6.1 C",
        "verdict": "Pass"
      },
      {
        "parameter": "Run hours, circuit 1",
        "value": "31,480 hours",
        "limit": "Trend only",
        "previous": "30,910 hours",
        "verdict": "Recorded"
      },
      {
        "parameter": "Run hours, circuit 2",
        "value": "29,660 hours",
        "limit": "Trend only",
        "previous": "29,455 hours",
        "verdict": "Recorded"
      }
    ],
    "consumables": [
      {
        "item": "Panel fasteners, stainless",
        "quantity": "2",
        "covered_by_contract": "Yes"
      },
      {
        "item": "Schrader valve cores",
        "quantity": "4",
        "covered_by_contract": "Yes"
      },
      {
        "item": "Coil cleaning chemical, non acidic",
        "quantity": "5 litres",
        "covered_by_contract": "Yes"
      },
      {
        "item": "Refrigerant R-32 for top up after repair",
        "quantity": "None added, held until the leak is repaired",
        "covered_by_contract": "No, quoted with the repair"
      }
    ],
    "defects": [
      {
        "reference": "DEF-2026-0417",
        "description": "Refrigerant leak at the circuit 2 liquid line schrader port, confirmed with an electronic detector and bubble solution. The port cap was missing and the core seal is worn rather than damaged. Circuit 2 is undercharged, which explains the overnight low pressure lockouts and the high superheat.",
        "severity": "High, circuit unavailable",
        "action": "Return visit to recover the remaining charge, replace the schrader core and cap, pressure test, evacuate and recharge by weight, then leak check again and log the charge",
        "owner": "Kestrel M&E, quoted separately as it falls outside the planned scope"
      },
      {
        "reference": "DEF-2026-0418",
        "description": "Glycol concentration has fallen from 27 percent to 22 percent across two visits, which suggests dilution from make up water rather than normal loss. The sample was drawn from the drain point and tested twice with the same result. Freeze protection is below the design figure before winter.",
        "severity": "Medium, seasonal",
        "action": "Trace the make up water path and check the fill valve, then correct the concentration by dosing and retest",
        "owner": "Brookmill Estates Management to name the water treatment contractor, Kestrel to retest on the next visit"
      }
    ],
    "tasks_deferred": "Annual compressor vibration survey and the evaporator inspection are scheduled with the summer visit and were not due on this one.",
    "deferral_reason": "Interval based, not deferred by circumstance. No task in the quarterly list was skipped on this visit.",
    "asset_state_on_departure": "Circuit 1 running under automatic control and holding setpoint. Circuit 2 left isolated at the controller with the site team informed, pending the leak repair. Cooling capacity is reduced but the block is served.",
    "overall_condition": "Serviceable with two open defects. For a unit in its eighth season the mechanical condition is good, and both defects are repairable rather than end of life indicators.",
    "next_visit_due": "January 2027, quarterly interval, subject to the leak repair visit happening first",
    "engineer_declaration": "I confirm the tasks marked complete were carried out, the readings are those I measured, and the defects listed are those found on this visit.",
    "witnessed_by": "Hana Duarte, Facilities Coordinator, Brookmill Estates Management Ltd",
    "witnessed_date": "October 8, 2026"
  }
}
JSON

tmpl_your_template_id is a stand-in: build this template in the visual editor and copy the id it shows, or create one with POST /api/v1/templates. Keys, formats, strict mode and batches are in the API reference.

Or let an AI assistant do it

The DocMake MCP server lets Claude and other assistants make this document the same way. Install it once:

claude mcp add docmake \
  --env DOCMAKE_API_KEY=dm_your_api_key \
  -- npx -y @docmake/mcp@latest

Then ask for the document in plain words:

Make a PDF from my Preventive Maintenance Checklist template with visit reference "PPM-2026-1194" and visit date "October 8, 2026".

How the MCP server works →

More operations templates