# Writing a .well by hand

> Habits that keep a hand-written .well file valid and faithful as it grows, from the order of blocks to ids, dates and test readings.

Most files are written by software, but a hand-written file is often the fastest way to record a single well, prepare test data or fix a detail. This guide collects the habits that keep such a file valid. Start from [Your first .well file](/format/getting-started/first-well-file) if you have not written one yet.

## Start from something valid

Copy an [example well](/format/reference/examples) that resembles yours, or the minimal file from the first-file guide, and change it step by step. Validate after each block you add (see [Validating](/format/guides/validating)): an error is easier to find in ten new lines than in three hundred.

A JSON-aware editor helps. In VS Code, associate the extension with JSON (`"files.associations": { "*.well": "json" }` in your settings) and add a `$schema` member at the top of the file. You then get completion and inline errors from the published schema:

```json
{
  "$schema": "https://welldot.org/schema/v2/well.schema.json",
  "version": "2.4"
}
```

`$schema` is an unknown member to the format, so readers keep it; the example wells carry one.

## Keep the report's meaning

- **Transcribe, do not interpret.** Free-text fields (`description`, `notes`, `obs`) keep the report's own words and language. Open vocabulary fields, such as a casing `type`, take the recommended value the report states, or an `x-` value for anything else; an unprefixed custom value is valid but not recommended ([custom vocabulary values](/format/spec/v2/format-reference#custom-vocabulary-values--x--prefix)).
- **Leave out what you do not know.** A missing value is omitted, never written as `null`, `0` or an empty string ([absent values](/format/spec/v2/format-reference#absent-values-since-v24)).
- **Convert units once, carefully.** Meters, millimeters and m³/h only ([Units and precision](/format/concepts/units-and-precision)). Write the real outer diameter of a casing, not its nominal size.

## Required fields

`version` and `well_type` are required by the spec ([core identity](/format/spec/v2/format-reference#core-identity)). `bore_hole`, `well_case`, `reduction`, `well_screen`, `surface_case`, `hole_fill`, `lithology`, `fractures` and `caves` must be present, even as `[]` ([Well object](/format/reference/objects/well)). Every other block can be left out entirely.

::note
`parseWell` in `@welldot/core` currently accepts a file without `well_type`. Write it anyway: the spec requires it, and other readers may reject the file.
::

::note
`parseWell` in `@welldot/core` currently accepts a file without `version`. The spec says such a file SHOULD be rejected ([parser version handling](/format/spec/v2/format-reference#parser-version-handling)), so always write it.
::

## Ids and references

Records in the history, tests, permits, meters, production and samples have an `id`. Ids are strings, unique within their block. UUIDs are recommended for software; short readable ids such as `evt-01` or `am-2025` are fine by hand ([`id` field convention](/format/spec/v2/format-reference#id-field-convention)).

References use those ids: an analysis lists the tests it used in `source_event_ids`, a log entry points to a sample in `sample_ids`. Every reference resolves within the same file ([cross-array references](/format/spec/v2/format-reference#cross-array-references)).

```json
"hydrodynamic_events": [
  { "id": "evt-01", "type": "constant_rate", "datetime": "2019-05-20T08:00:00-03:00", "static_level": 3.9 }
],
"aquifer_analysis": [
  { "id": "an-01", "datetime": "2019-06-02T10:00:00-03:00", "source_event_ids": ["evt-01"], "method": "cooper_jacob" }
]
```

::warning
Two records with the same id in one block make the file malformed. Software must not guess which one you meant ([duplicate ids](/format/spec/v2/format-reference#duplicate-ids-within-a-scope)).
::

## Dates and times

- Construction dates and permit dates are calendar dates: `"2019-05-20"`.
- Everything that was measured or happened at a moment is an instant with its UTC offset: `"2019-05-20T08:00:00-03:00"`. An instant without an offset is invalid ([datetime conventions](/format/spec/v2/format-reference#datetime-conventions)).
- If the report gives only the day of a test, write the local time you know (often the start of the working day) and say so in `notes`.

## Pumping tests

A test is one event. Its readings sit inside steps:

```json
{
  "id": "evt-02",
  "type": "constant_rate",
  "datetime": "2019-05-20T08:00:00-03:00",
  "static_level": 3.94,
  "steps": [
    {
      "rate": 18,
      "duration": 1440,
      "readings": [
        { "elapsed": 1, "depth": 9.8 },
        { "elapsed": 60, "depth": 14.2 },
        { "elapsed": 1440, "depth": 15.1 }
      ]
    }
  ],
  "recovery": {
    "readings": [
      { "elapsed": 1, "depth": 10.4 },
      { "elapsed": 120, "depth": 4.3 }
    ]
  }
}
```

`rate` is m³/h, `duration` and `elapsed` are minutes from the start of the step, and `depth` is the water level in meters below ground. Do not store drawdown, specific capacity or Jacob coefficients on the event: drawdown is derived from the readings, and interpretations go in `aquifer_analysis` ([design principles](/format/spec/v2/overview#design-principles), "Derived values are never stored raw"). The step and reading schemas are [`PumpingStep`](/format/spec/v2/object-schemas#pumpingstep) and [`LevelReading`](/format/spec/v2/object-schemas#levelreading).

## Corrections

To correct a measurement after a file has been shared, add a new entry whose `corrects` holds the id of the wrong one, instead of editing it. The old entry stays in the file and drops out of every calculation ([corrections](/format/spec/v2/object-schemas#corrections-since-v23)). This applies to `hydrodynamic_events`, `production` and `water_samples`, the three ledger blocks ([block kinds](/format/spec/v2/format-reference#block-kinds-since-v23)).

## When the file grows

Past a few hundred lines, a hand-written file is easier to maintain in the [welldot.org](https://welldot.org) editor, which opens and saves the same file. For many wells, write a script with [`@welldot/core`](/core) instead.
