DocMake
The PDF DocMake makes from the Field Service Report template

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

Operations

Field Service Report

A field service report is the record of one visit to one asset. It says who attended, when they arrived and left, what was found, what was done, which parts went in, and whether the asset was left running. For a service business it is the document that turns a van movement into something that can be invoiced, warranted or defended, and it is signed on site while the customer is still standing next to the machine.

Time is where these reports earn their keep. Travel out, time on site, waiting time and a labour line per engineer are four different numbers, and a service contract usually treats them four different ways. A visit inside a maintenance contract is covered, the same visit outside contract hours is not, and the second engineer sent to lift a compressor is charged even when the first one is not. Recording the lines separately, each with its own rate basis, is the difference between an invoice that gets paid and one that gets queried.

The narrative wants the same discipline: symptom, cause, action, result. An engineer who writes only that a unit was repaired leaves nobody able to spot the same fault appearing on three sites in a month. Naming the failed component, the reading that proved it, and the reading after the fix turns a pile of visits into reliability data. It also settles the awkward cases, because a report that says the asset was left off, with the reason and who agreed to it, protects everyone once the building gets warm.

The last block matters more than it looks. Work not completed, parts on order, quotes to follow and recommendations are what generate the next job, and a report that ends at the signature line quietly drops that revenue. Rendering the whole thing from JSON means the engineer files a mobile form, the API returns a branded PDF, and the customer has it in their inbox before the van leaves the car park, as many times a day as there are visits, from a single template.

Blanks to fill

report_number Report number
visit_date Visit date
service_company Service company
contract_reference Contract reference
call_type Call type
priority Priority
customer Customer
site_name Site
site_address Site address
site_contact Site contact
site_contact_phone Site contact phone
asset_id Asset tag
asset_location Asset location
asset_description Asset
manufacturer Manufacturer
model Model
serial_number Serial number
warranty_reference Warranty reference
reported_fault Fault as reported
arrival_time Arrival
departure_time Departure
travel_time Travel time
findings Findings
root_cause Cause
work_carried_out Work carried out
asset_status_on_departure Asset status on departure
work_completed Work complete
recommendations Recommendations
safety_observations Safety observations
engineer_name Engineer
engineer_signature_note Engineer declaration
signed_at Signed
customer_signatory Signed on site by
customer_signature_note Customer declaration
company_name Company
labour_lines[] One per item, so a row is added for every item in the list
parts[] One per item, so a row is added for every item in the list
tests[] One per item, so a row is added for every item in the list
outstanding[] 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",
  "report_number": "FSR-2026-4417",
  "visit_date": "October 6, 2026",
  "service_company": "Kestrel M&E Ltd",
  "contract_reference": "Defects liability, Cascade Street M&E package, handover HC-2026-0031",
  "call_type": "Reactive callout, within the defects liability period",
  "priority": "P2, comfort cooling lost to one floor, four hour response",
  "customer": "Cascade Street Holdings LLC",
  "site_name": "Cascade Street mixed use development",
  "site_address": "Cascade Street, Bristol BS1 6TR, United Kingdom",
  "site_contact": "Owen Marsh, Building Manager",
  "site_contact_phone": "0117 496 2210",
  "asset_id": "AHU-03",
  "asset_description": "Air handling unit serving level 3 open plan office, 4.2 cubic metres per second supply",
  "asset_location": "Level 4 plant room, east bay",
  "manufacturer": "Alderfen Air Systems",
  "model": "AFA-4200-HR",
  "serial_number": "AFA-4200-2026-118",
  "warranty_reference": "WC-2026-0442, twenty four months from October 2, 2026",
  "reported_fault": "Supply air warm on level 3 from mid morning. Building management system showing the cooling coil valve at 100 percent with no drop in off coil temperature.",
  "arrival_time": "09:12",
  "departure_time": "13:40",
  "travel_time": "0.6 hours each way from the Avonmouth depot",
  "findings": "Chilled water flow to the coil was almost nil. The two port control valve on the coil return was driving open at the actuator but the spindle was not moving, and the coupling grub screw was found loose in the actuator body. Strainer at the branch was clean, differential pressure across the branch was normal, so the coil and the pump were both ruled out.",
  "root_cause": "Actuator coupling not torqued at commissioning. The spindle turned freely by hand once the actuator was lifted, which put the fault on the coupling rather than on the valve or the control signal.",
  "work_carried_out": "Isolated and drained the coil branch, removed the actuator, replaced the coupling assembly and torqued to the manufacturer figure, refitted and re-stroked the actuator through the full range from the building management system, refilled and vented the branch, then ran the unit for forty minutes and logged off coil temperatures until they were stable.",
  "labour_lines": [
    {
      "engineer": "Priya Raman",
      "activity": "Diagnosis and repair",
      "hours": "3.5",
      "rate_basis": "Defects liability, no charge",
      "chargeable": "No, covered by the contract"
    },
    {
      "engineer": "Priya Raman",
      "activity": "Travel, depot to site and return",
      "hours": "1.2",
      "rate_basis": "Defects liability, no charge",
      "chargeable": "No, covered by the contract"
    },
    {
      "engineer": "Tom Beddoe",
      "activity": "Second engineer, valve isolation and refill",
      "hours": "1.5",
      "rate_basis": "Defects liability, no charge",
      "chargeable": "No, covered by the contract"
    },
    {
      "engineer": "Priya Raman",
      "activity": "Filter change requested by the building manager while on site",
      "hours": "0.5",
      "rate_basis": "Contract rate, standard hours",
      "chargeable": "Yes, contract rate"
    }
  ],
  "parts": [
    {
      "code": "AFA-CPL-24",
      "description": "Actuator coupling kit, 24 mm spindle, with grub screws and shims",
      "quantity": "1",
      "source": "Van stock",
      "old_part_returned": "Yes, returned to the depot with the report"
    },
    {
      "code": "FLT-G4-592",
      "description": "Panel filter G4, 592 by 592 by 48 mm",
      "quantity": "4",
      "source": "Van stock",
      "old_part_returned": "No, disposed of on site as waste"
    },
    {
      "code": "GSK-DN40",
      "description": "Flange gasket DN40, EPDM",
      "quantity": "2",
      "source": "Van stock",
      "old_part_returned": "No, disposed of on site as waste"
    }
  ],
  "tests": [
    {
      "check": "Off coil air temperature after forty minutes",
      "reading": "12.4 C",
      "expected": "12 C to 14 C",
      "result": "Pass"
    },
    {
      "check": "Chilled water flow and return across the coil",
      "reading": "6.1 C flow, 11.8 C return",
      "expected": "6 C flow, 12 C return nominal",
      "result": "Pass"
    },
    {
      "check": "Valve stroke, closed to open, from the building management system",
      "reading": "0 to 100 percent in 92 seconds, full travel confirmed at the spindle",
      "expected": "Full travel within 120 seconds",
      "result": "Pass"
    },
    {
      "check": "Supply air temperature at the level 3 index diffuser",
      "reading": "13.9 C",
      "expected": "Below 16 C",
      "result": "Pass"
    },
    {
      "check": "Filter differential pressure after change",
      "reading": "48 Pa",
      "expected": "Below 120 Pa clean",
      "result": "Pass"
    }
  ],
  "asset_status_on_departure": "Running and back under building management system control, cooling proved on level 3, no alarms outstanding at the head end",
  "work_completed": "Yes, the repair is complete and the unit is back in service. Two items are carried forward below.",
  "outstanding": [
    {
      "item": "Coupling torque on the remaining eight control valves in the level 4 plant room",
      "action": "Check and torque the couplings on AHU-01, AHU-02, AHU-04 and the four fan coil branches, same batch and same commissioning date",
      "owner": "Kestrel M&E, service desk to schedule",
      "target_date": "October 16, 2026"
    },
    {
      "item": "Level 3 space temperature trend",
      "action": "Pull a seven day trend from the building management system to confirm the space is holding setpoint before the call is closed",
      "owner": "Owen Marsh, Building Manager",
      "target_date": "October 14, 2026"
    }
  ],
  "recommendations": "The failed coupling came from the same installation batch as the other units in this plant room, so the visit is being treated as a batch check rather than a one off repair. The panel filters were at the end of their service life and were changed on request; the building manager may want the filter change folded into the quarterly maintenance visit rather than raised as a separate call each time.",
  "safety_observations": "Plant room access was clear and the permit board was current. One spare filter carton was blocking the escape route from the east bay and was moved to the store before the engineers left site.",
  "engineer_name": "Priya Raman",
  "engineer_signature_note": "I confirm the work described above was carried out and the readings recorded are those I measured on site.",
  "customer_signatory": "Owen Marsh, Building Manager",
  "customer_signature_note": "Signed to confirm the engineer attended, the work described was witnessed, and the asset was left in the condition stated. Signing does not accept any charge shown.",
  "signed_at": "October 6, 2026, 13:38"
}

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-field-service-report.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 field-service-report.pdf \
  --data-binary @- <<'JSON'
{
  "template_id": "tmpl_your_template_id",
  "format": "pdf",
  "data": {
    "company_name": "Kestrel M&E Ltd",
    "report_number": "FSR-2026-4417",
    "visit_date": "October 6, 2026",
    "service_company": "Kestrel M&E Ltd",
    "contract_reference": "Defects liability, Cascade Street M&E package, handover HC-2026-0031",
    "call_type": "Reactive callout, within the defects liability period",
    "priority": "P2, comfort cooling lost to one floor, four hour response",
    "customer": "Cascade Street Holdings LLC",
    "site_name": "Cascade Street mixed use development",
    "site_address": "Cascade Street, Bristol BS1 6TR, United Kingdom",
    "site_contact": "Owen Marsh, Building Manager",
    "site_contact_phone": "0117 496 2210",
    "asset_id": "AHU-03",
    "asset_description": "Air handling unit serving level 3 open plan office, 4.2 cubic metres per second supply",
    "asset_location": "Level 4 plant room, east bay",
    "manufacturer": "Alderfen Air Systems",
    "model": "AFA-4200-HR",
    "serial_number": "AFA-4200-2026-118",
    "warranty_reference": "WC-2026-0442, twenty four months from October 2, 2026",
    "reported_fault": "Supply air warm on level 3 from mid morning. Building management system showing the cooling coil valve at 100 percent with no drop in off coil temperature.",
    "arrival_time": "09:12",
    "departure_time": "13:40",
    "travel_time": "0.6 hours each way from the Avonmouth depot",
    "findings": "Chilled water flow to the coil was almost nil. The two port control valve on the coil return was driving open at the actuator but the spindle was not moving, and the coupling grub screw was found loose in the actuator body. Strainer at the branch was clean, differential pressure across the branch was normal, so the coil and the pump were both ruled out.",
    "root_cause": "Actuator coupling not torqued at commissioning. The spindle turned freely by hand once the actuator was lifted, which put the fault on the coupling rather than on the valve or the control signal.",
    "work_carried_out": "Isolated and drained the coil branch, removed the actuator, replaced the coupling assembly and torqued to the manufacturer figure, refitted and re-stroked the actuator through the full range from the building management system, refilled and vented the branch, then ran the unit for forty minutes and logged off coil temperatures until they were stable.",
    "labour_lines": [
      {
        "engineer": "Priya Raman",
        "activity": "Diagnosis and repair",
        "hours": "3.5",
        "rate_basis": "Defects liability, no charge",
        "chargeable": "No, covered by the contract"
      },
      {
        "engineer": "Priya Raman",
        "activity": "Travel, depot to site and return",
        "hours": "1.2",
        "rate_basis": "Defects liability, no charge",
        "chargeable": "No, covered by the contract"
      },
      {
        "engineer": "Tom Beddoe",
        "activity": "Second engineer, valve isolation and refill",
        "hours": "1.5",
        "rate_basis": "Defects liability, no charge",
        "chargeable": "No, covered by the contract"
      },
      {
        "engineer": "Priya Raman",
        "activity": "Filter change requested by the building manager while on site",
        "hours": "0.5",
        "rate_basis": "Contract rate, standard hours",
        "chargeable": "Yes, contract rate"
      }
    ],
    "parts": [
      {
        "code": "AFA-CPL-24",
        "description": "Actuator coupling kit, 24 mm spindle, with grub screws and shims",
        "quantity": "1",
        "source": "Van stock",
        "old_part_returned": "Yes, returned to the depot with the report"
      },
      {
        "code": "FLT-G4-592",
        "description": "Panel filter G4, 592 by 592 by 48 mm",
        "quantity": "4",
        "source": "Van stock",
        "old_part_returned": "No, disposed of on site as waste"
      },
      {
        "code": "GSK-DN40",
        "description": "Flange gasket DN40, EPDM",
        "quantity": "2",
        "source": "Van stock",
        "old_part_returned": "No, disposed of on site as waste"
      }
    ],
    "tests": [
      {
        "check": "Off coil air temperature after forty minutes",
        "reading": "12.4 C",
        "expected": "12 C to 14 C",
        "result": "Pass"
      },
      {
        "check": "Chilled water flow and return across the coil",
        "reading": "6.1 C flow, 11.8 C return",
        "expected": "6 C flow, 12 C return nominal",
        "result": "Pass"
      },
      {
        "check": "Valve stroke, closed to open, from the building management system",
        "reading": "0 to 100 percent in 92 seconds, full travel confirmed at the spindle",
        "expected": "Full travel within 120 seconds",
        "result": "Pass"
      },
      {
        "check": "Supply air temperature at the level 3 index diffuser",
        "reading": "13.9 C",
        "expected": "Below 16 C",
        "result": "Pass"
      },
      {
        "check": "Filter differential pressure after change",
        "reading": "48 Pa",
        "expected": "Below 120 Pa clean",
        "result": "Pass"
      }
    ],
    "asset_status_on_departure": "Running and back under building management system control, cooling proved on level 3, no alarms outstanding at the head end",
    "work_completed": "Yes, the repair is complete and the unit is back in service. Two items are carried forward below.",
    "outstanding": [
      {
        "item": "Coupling torque on the remaining eight control valves in the level 4 plant room",
        "action": "Check and torque the couplings on AHU-01, AHU-02, AHU-04 and the four fan coil branches, same batch and same commissioning date",
        "owner": "Kestrel M&E, service desk to schedule",
        "target_date": "October 16, 2026"
      },
      {
        "item": "Level 3 space temperature trend",
        "action": "Pull a seven day trend from the building management system to confirm the space is holding setpoint before the call is closed",
        "owner": "Owen Marsh, Building Manager",
        "target_date": "October 14, 2026"
      }
    ],
    "recommendations": "The failed coupling came from the same installation batch as the other units in this plant room, so the visit is being treated as a batch check rather than a one off repair. The panel filters were at the end of their service life and were changed on request; the building manager may want the filter change folded into the quarterly maintenance visit rather than raised as a separate call each time.",
    "safety_observations": "Plant room access was clear and the permit board was current. One spare filter carton was blocking the escape route from the east bay and was moved to the store before the engineers left site.",
    "engineer_name": "Priya Raman",
    "engineer_signature_note": "I confirm the work described above was carried out and the readings recorded are those I measured on site.",
    "customer_signatory": "Owen Marsh, Building Manager",
    "customer_signature_note": "Signed to confirm the engineer attended, the work described was witnessed, and the asset was left in the condition stated. Signing does not accept any charge shown.",
    "signed_at": "October 6, 2026, 13:38"
  }
}
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 Field Service Report template with report number "FSR-2026-4417" and visit date "October 6, 2026".

How the MCP server works →

More operations templates