Format 1.0

The record as data

The builder saves every record as a small JSON file. The format is open (MIT), versioned, and described by a JSON Schema, so any tool can read and write it.

JSON Schema draft 2020-12. Schema id: https://openrepairrecord.com/schema/orr-1.0.schema.json

Build a record, step by step

One fictional repair, written as a file one part at a time. Scroll, and the part being explained lights up. The same nine parts are the sections of the builder and of the printed report.

  1. 1Fundamentals

    Every record starts with the format version and your own job number, so any tool knows how to read it and anyone can match it to the original job card.

  2. 2What was reported

    Where, when, who reported it, and the symptom in the reporter's own words. The diagnosis stays out of here: it is the contractor's view, and goes in their statement.

  3. 3What the contractor says

    One entry per visit, each with a name and a time. The outcome is what the contractor reports, not a verdict: resolved, temporary fix, partly done, not done, or no access.

  4. 4Checks

    Who checked, how, what they found, and what they did not cover. Here the technician ran a 15-minute test, and the coordinator reviewed the photo but did not inspect the unit.

  5. 5Evidence

    What backs a statement or a check, with what it shows and who made it. Files stay where they are; the record only names them. Evidence is never required.

  6. 6The resident

    The answer to one question: is the problem solved? This resident was asked on 11 Oct and never answered, so the record says no_reply, with the date. Silence is never a yes.

  7. 7Still open

    Anything left to do, with an owner and a date. Empty here, because the contractor reports a full fix. A temporary fix would need an entry.

  8. 8Closure

    Closing is a decision, so it has an author and a reason. This job was closed as "work reported done, no reply from the resident": honest, and good enough.

  9. 9Later additions

    Whatever comes later is added, never rewritten: a late reply, a revisit, a correction. If the record is reopened, the old closure is kept here exactly as it was.

Q-1204.orr.json
{
  "orr_version": "1.0",
  "id": "Q-1204",
  "title": "AC dripping water",
  "context": {
    "location": "Tower 2, Apartment 1204",
    "area": "unit",
    "asset": "Split AC, living room",
    "reported_at": "2026-10-10T16:05",
    "reported_by_role": "resident",
    "symptom": "Water is dripping from the AC in the living room."
  },
  "work": [
    {
      "by": {
        "name": "Ravi Kumar",
        "company": "Bluepoint Cooling",
        "role": "AC technician"
      },
      "at": "2026-10-11T10:30",
      "done": "Cleared the blocked condensate drain, then ran the unit for 15 minutes and watched it: no leak during that time.",
      "diagnosis": "Blocked condensate drain.",
      "outcome": "resolved"
    }
  ],
  "checks": [
    {
      "by_role": "technician",
      "by_name": "Ravi Kumar",
      "at": "2026-10-11T10:50",
      "method": "test_run",
      "result": "Ran the unit for 15 minutes: no water leaked while watching.",
      "limits": "15 minutes only."
    },
    {
      "by_role": "coordinator",
      "by_name": "Lina Haddad",
      "at": "2026-10-11T14:00",
      "method": "photo_review",
      "result": "The technician's photo and test note are on file.",
      "limits": "Did not inspect the unit."
    }
  ],
  "evidence": [
    {
      "type": "photo",
      "description": "The drain line after cleaning.",
      "taken_by": "Ravi Kumar",
      "taken_at": "2026-10-11T10:48",
      "reference": "Q-1204-drain.jpg"
    },
    {
      "type": "test_log",
      "description": "Technician's note: 15-minute test run, no leak seen.",
      "taken_by": "Ravi Kumar",
      "taken_at": "2026-10-11T10:50"
    }
  ],
  "resident": {
    "status": "no_reply",
    "asked_at": "2026-10-11T14:05",
    "channel": "WhatsApp"
  },
  "open_items": [],
  "status": "closed",
  "closure": {
    "closed_by": {
      "name": "Lina Haddad",
      "role": "Maintenance coordinator"
    },
    "closed_at": "2026-10-15T09:00",
    "reason_code": "work_reported_done_no_reply",
    "reason": "Work reported as done. Asked the resident on 11 Oct; no reply after four days."
  },
  "history": [
    {
      "at": "2026-10-16T08:40",
      "by": "Lina Haddad",
      "kind": "note",
      "text": "Sent this report to the owner as a PDF."
    }
  ]
}

Field reference

Every field, with what it means. Generated from the JSON Schema, so this table and the schema always say the same thing. Only the fields marked required must be present; everything else is written when you know it.

Fundamentals

FieldTypeWhat it means
orr_versionrequired always "1.0" The version of this format. Always "1.0" for files written against this schema, so a reader knows which rules apply.
id text Your own reference for the job: the ticket, work order or job card number in your system. Lets anyone match the record to the original job.
e.g. Q-1204
title text A short, human title for the record. Optional: the report falls back to the symptom.
e.g. AC dripping water
timezone text IANA time zone of the property, when the dates need it to be unambiguous. Dates without an offset are read in this zone.
e.g. Asia/Qatar
related_ids[] list Other records about the same problem, such as an earlier job that was closed and came back.

What was reported

FieldTypeWhat it means
contextrequired group What was reported: where, when, by whom, and the symptom in the reporter's own words. The diagnosis does not go here; it belongs to the contractor's statement.
context.location text Where the problem is: the building and unit, or the common area.
e.g. Tower 2, Apartment 1204
context.area one of
unitcommon_area
unit: inside one home, where a resident can be asked. common_area: lobby, plant room, car park, lifts; nobody to ask, so the resident's answer is not_applicable.
context.asset text The equipment, if known: an asset tag from your register or a plain label. Lets repeat faults on the same equipment be found later.
e.g. Split AC, living room
context.reported_at date When the problem was reported.
e.g. 2026-10-11T10:30
context.reported_by_role one of
residentownerstaffinspectionother
Who reported it: the resident, the owner, your own staff, a planned inspection, or someone else.
context.symptom text What was reported, in the reporter's terms. Keep it as reported: if the fault comes back, this is what you compare against.
e.g. Water is dripping from the AC in the living room.

What the contractor says

FieldTypeWhat it means
work[]required list What the contractor says, one entry per visit or report of work, oldest first. Each entry is a statement with a name and a time, not a verdict.
work[].by group Who made the statement: the technician, and their company.
work[].by.name text The person's name.
work[].by.company text Their company.
work[].by.role text Their role, e.g. AC technician or maintenance coordinator.
work[].at date When the work was done, or when the statement was made.
e.g. 2026-10-11T10:30
work[].done text What the contractor says was done, in their words.
e.g. Cleared the blocked condensate drain, then ran the unit for 15 minutes.
work[].diagnosis text The contractor's view of the cause, if known.
e.g. Blocked condensate drain.
work[].outcome one of
resolvedtemporary_fixpartialnot_doneno_access
The outcome the contractor reports. resolved: they believe the fault is fixed. temporary_fix: the symptom is stopped, the real repair is still to come. partial: some of the work is done. not_done: they came but could not do it. no_access: nobody let them in.
work[].follow_up_needed yes / no True when the contractor says another visit or more work is needed.
work[].follow_up text What that follow-up is.
e.g. Fit the new drain pan when it arrives.

Checks

FieldTypeWhat it means
checks[]required list Anything someone did to confirm the work, oldest first. Each check says who, how, what they found, and what they did not cover. Empty when nobody checked: that is allowed, and the report says so.
checks[].by_role one of
techniciancoordinatorinspectorresidentother
Who checked: the technician themselves, your coordinator, an inspector, the resident, or someone else.
checks[].by_name text The name of the person who checked.
checks[].at date When the check was done.
e.g. 2026-10-11T10:30
checks[].method one of
test_runmeasurementvisualphoto_reviewother
How it was checked: running the equipment, measuring something, looking at it, reviewing a photo, or another way.
checks[].result text What the check found.
e.g. Ran the unit for 15 minutes: no water leaked while watching.
checks[].limits text What the check did not cover. As useful as the result: it tells the reader where the knowledge stops.
e.g. Did not inspect the unit.

Evidence

FieldTypeWhat it means
evidence[]required list What backs a statement or a check: photos, measurements, test logs, certificates. Never required. The record lists them; it does not store or upload them.
evidence[].type one of
photomeasurementtest_logcertificatedocumentother
What kind of evidence it is.
evidence[].description text What it shows. A photo shows what it shows; say what that is.
e.g. The drain line after cleaning.
evidence[].taken_by text Who made it.
evidence[].taken_at date When it was made.
e.g. 2026-10-11T10:30
evidence[].reference text A file name or a link to where it is kept. Nothing is uploaded.
e.g. Q-1204-drain.jpg

The resident

FieldTypeWhat it means
residentrequired group The resident's answer to one question: is the problem they reported solved, in their view?
resident.statusrequired one of
resolvednot_resolvednot_askedpendingno_replynot_applicable
resolved: they say it is solved. not_resolved: they say it is not. not_asked: nobody asked yet. pending: asked, waiting for an answer. no_reply: asked and nothing came back; stays no_reply, silence is never a confirmation. not_applicable: there is no resident to ask (common areas).
resident.asked_at date When the resident was asked. This is what makes no_reply meaningful.
e.g. 2026-10-11T10:30
resident.answered_at date When the resident answered.
e.g. 2026-10-11T10:30
resident.words text The resident's own words, quoted as written.
e.g. It's dripping again, same place.
resident.channel text How they were asked or answered.
e.g. WhatsApp

Still open

FieldTypeWhat it means
open_items[]required list Anything still left to do. A temporary fix or partial work needs at least one entry, with an owner and a date.
open_items[].what text What is still open.
e.g. Fit the new drain pan.
open_items[].owner text Who owns it.
e.g. Ravi Kumar, Bluepoint Cooling
open_items[].next_step text The next concrete step.
open_items[].due date By when.
e.g. 2026-10-11T10:30

Closure

FieldTypeWhat it means
statusrequired one of
openclosed
Whether the record is open or closed. Closing is a decision someone takes; the closure says who and why.
closure group Present only while the record is closed: who closed it, when, and why.
closure.closed_by group Who closed it.
closure.closed_by.name text The person's name.
closure.closed_by.company text Their company.
closure.closed_by.role text Their role, e.g. AC technician or maintenance coordinator.
closure.closed_at date When it was closed.
e.g. 2026-10-11T10:30
closure.reason_code one of
confirmed_by_residentwork_reported_done_no_replyadministrativeduplicatecancelledother
Why. confirmed_by_resident: the resident said it is solved (needs resident.status resolved). work_reported_done_no_reply: the contractor reported it done and the resident did not answer. administrative: closed for an organisational reason, explained in reason. duplicate: the same problem is tracked in another record. cancelled: the job was cancelled. other: explained in reason.
closure.reason text The reason in your own words.
e.g. Work reported as done. Asked the resident on 11 Oct; no reply after four days.

Later additions

FieldTypeWhat it means
history[]required list Later additions, oldest first: a late reply, a revisit, a correction, a reopening. Earlier entries are never rewritten; changes are added here.
history[].at date When this was added.
e.g. 2026-10-11T10:30
history[].by text Who added it.
history[].kind one of
resident_replyrevisitcorrectionreopenednote
resident_reply: an answer that came in later. revisit: another visit. correction: a fix to something written earlier, without rewriting it. reopened: a closed record was opened again. note: anything else.
history[].text text What the addition says.
history[].previous_closure group For reopened: the closure that was in force before, kept exactly as it was.
history[].previous_closure.closed_by group Who closed it.
history[].previous_closure.closed_by.name text The person's name.
history[].previous_closure.closed_by.company text Their company.
history[].previous_closure.closed_by.role text Their role, e.g. AC technician or maintenance coordinator.
history[].previous_closure.closed_at date When it was closed.
e.g. 2026-10-11T10:30
history[].previous_closure.reason_code one of
confirmed_by_residentwork_reported_done_no_replyadministrativeduplicatecancelledother
Why. confirmed_by_resident: the resident said it is solved (needs resident.status resolved). work_reported_done_no_reply: the contractor reported it done and the resident did not answer. administrative: closed for an organisational reason, explained in reason. duplicate: the same problem is tracked in another record. cancelled: the job was cancelled. other: explained in reason.
history[].previous_closure.reason text The reason in your own words.
e.g. Work reported as done. Asked the resident on 11 Oct; no reply after four days.

Dates are ISO 8601 as written: 2026-10-12 or 2026-10-12T14:20, in the property's local time unless an offset is given. Text is free text: the format does not impose code lists beyond the few choices above, which every report needs so that it is read the same way.

Rules

The schema checks the shape. A few rules are about meaning, and the builder's check applies them:

  • resident.status no_reply stays no_reply. No tool should turn silence into resolved.
  • An open record has no closure. Reopening moves the old closure into history[].previous_closure, unchanged.
  • closure.reason_code confirmed_by_resident needs resident.status resolved.
  • A latest work outcome of temporary_fix or partial needs at least one open_items entry.
  • not_applicable is for common areas. Evidence is never required.
  • Entries are added, not rewritten. Corrections go in history.

Example files

How it relates to existing models

Open Repair Record is a practical guide and a small format for one report. It is not a new data standard for housing, and it does not replace the models that already exist:

  • HACT UK Housing Data Standards cover reactive repairs among much else. We have not mapped ORR to them; if you use them, keep using them.
  • MIMOSA CCOM, COBie and OSCRE model assets, completed work and property data in far more depth.

The closest public schema we have read is the damp-and-mould data standards proof of concept (data-futurists, MIT, 2025). Its own README says it is a proof of concept, not finalised, and not for live services. The table below is our informal reading of its work_order definitions, not an official mapping:

Open Repair RecordDamp-and-mould proof of conceptNote
idwork_order_id
context.reported_atdate_reported
context.locationaddress_id, location_of_repairtheirs is an address identifier plus where in the home
context.symptomdescription_of_worktheirs describes the problem from a schedule of rates or a local code
work[].atactual_start_date_time, actual_completion_date_timeORR keeps one time per statement
work[].bycontractor_organisation, work_order_complete.operatives_used
work[].donework_order_complete.completed_work_elements
work[].follow_up, open_items[]work_order_complete.follow_on_worktheirs is a single text field
status, closure, history[]work_order_status_history (status_code, reason, reason_code, created_date_time), job_status_updatecodes are free text in both
checks[], evidence[], residentno equivalent in the work_order definitions
not in ORRwork_priority, planned dates, estimated_cost, repair_sla_breach_flag, access information, alerts, trade and schedule-of-rates codesleft to the operator's own system

The gap is the point: work-order models describe the job; ORR adds who checked what, what the resident answered, and why the record was closed. If an existing model covers what you need, use it, and treat ORR as a guide for filling it in well.

Versions

The promise: every 1.x version only adds. A file written for 1.0 stays valid in 1.1, 1.2 and later, and its fields keep their meaning. Anything that would break a file waits for 2.0, and is announced here first.

VersionStatusWhat it brings
1.0Current
18 Oct 2026
The nine parts of a record, the JSON Schema, the builder with its check, print and PDF, five examples.
1.1PlannedA bilingual English and Arabic report, reviewed by a native speaker who knows local maintenance terms. Optional language field.
1.2PlannedA draft from a technician's note: each statement keeps the words it came from, and a person confirms it. Optional source on each entry.
1.3PlannedLinks to an asset register: equipment identifiers and a repeat-fault history for the same asset.

Planned versions are intentions, not dates. Tell us what you need first: support@pmfriend.com.