Specification

.well File Format Specification — Version 2.4: Format Reference

See also: overview.md · object-schemas.md · interoperability.md · water-quality.md

Overview

This part of the .well v2.4 specification defines the file as a whole: the top-level structure and fields, how versions and deprecations work, datetime conventions, the recommended values of every open vocabulary, well_id and location, the canonical units and which unit each field uses, profiles, the x- extension rules, cross-reference and uniqueness rules, and precision fields. The objects inside each block are specified in object-schemas.md.

Table of contents


Top-level Structure

{
  "version": "2.4",
  "@context": "https://welldot.org/context/v2.jsonld",

  "well_id": [ ... ],
  "location": { ... },

  "name": "...",
  "well_type": "...",
  "well_purpose": [ ... ],
  "well_driller": "...",
  "construction_date": "YYYY-MM-DD",
  "obs": "...",

  "profiles": [ ... ],

  "bore_hole": [ ... ],
  "well_case": [ ... ],
  "reduction": [ ... ],
  "well_screen": [ ... ],
  "surface_case": [ ... ],
  "hole_fill": [ ... ],
  "centralizers": [ ... ],
  "cement_pad": { ... },

  "lithology": [ ... ],
  "fractures": [ ... ],
  "caves": [ ... ],

  "hydrodynamic_events": [ ... ],
  "aquifer_analysis": [ ... ],
  "history_logs": [ ... ],

  "attachments": [ ... ],
  "pump_installations": [ ... ],
  "permits": [ ... ],
  "meters": [ ... ],
  "production": [ ... ],
  "operating_regime": [ ... ],

  "water_samples": [ ... ]
}

Absent values (since v2.4)

An optional field without a value is omitted, never written as null. A null in an optional field is malformed. Absent means unknown.

Readers accept null in aquifer_analysis[].storativity only in files whose version is the integer 2, and treat it as absent.


Versioning

VersionDescription
1Initial release — constructive and geologic data only
2Adds location, well_id (array), profiles, texture object, hydrodynamic_events, aquifer_analysis, history_logs, optional @context, *_precision fields, and extensibility conventions. Tightens unit semantics: all values are canonical SI, no per-file declaration.
"2.4"Version written as the string "M.m" (since v2.4). Read as v2; the integer 2 means v2.0 to v2.3.

Minor revisions (2.1, 2.3, …) are additive. Up to v2.3 they did not change the version integer: a v2.3 document declares "version": 2. A v2.0 parser reading a v2.1 document sees the v2.1 fields (well_purpose, centralizers) as unrecognized members without the x- prefix. Per § Extensibility it MUST preserve them and MUST NOT reject the file, and it SHOULD emit a warning.

The same rule applies to v2.3: a v2.0 or v2.1 parser reading a v2.3 document sees attachments, pump_installations, permits, meters, production, operating_regime, water_samples, hydrodynamic_events[].corrects, the history_logs data links (hydrodynamic_event_ids, sample_ids) and category-specific fields (maintenance, status_change) and the nested attachments arrays as unrecognized members. It MUST preserve them, MUST NOT reject the file, and SHOULD emit a warning. Such a parser does not know corrects, so it may still count a retracted event; this is the expected degradation.

(since v2.4) The version is written as the string "M.m" (for example "2.4"). Versions are compared as two integers, never as text: "2.10" is greater than "2.9". Patch levels ("2.4.1") are not allowed. The integer 2 means v2.0 to v2.3 with the revision unknown, and it remains valid for reading. There is no separate spec_version field.

Intentional break. A parser of @welldot/core 0.4.0 or earlier rejects "2.4" files because it only accepts the integers 1 and 2. This is the one intentional exception to the minor-revision compatibility rule above. Upgrade readers before writing v2.4 files.

Parser version handling

The version field MUST be written by producers. It takes one of three forms: the integer 1, the integer 2, or a string "M.m" matching ^\d+\.\d+$.

  • A version that is none of these forms (2.4 as a JSON number, "2.4.1", "v2.4", "2") is malformed. A parser MUST reject the file with an error that names the value.
  • A major other than 1 or 2 (3, "3.0") is unsupported. A parser MUST reject the file with an error that names the value.
  • Any minor of major 2 ("2.4", a future "2.9") is read as v2. Unknown members follow § Extensibility.
  • A v2 parser encountering version: 1 MUST apply the v1-to-v2 normalizations listed in the changes section and treat the document as v2-equivalent for all subsequent processing.
  • A v1 parser encountering version: 2 MUST reject the file with a clear error indicating an unsupported format version. v1 parsers MUST NOT attempt partial reads of v2 documents.
  • Either parser encountering an unrecognized integer version MUST reject the file with a clear error.
  • A file without a version field SHOULD be rejected. Parsers MAY emit a warning and attempt to read the file as v1 if all required v1 fields are present and no v2-specific blocks are detected, but this fallback behavior is implementation-specific and not guaranteed by the spec.

Files with version: 1 MUST NOT contain any v2-only blocks (hydrodynamic_events, aquifer_analysis, history_logs, attachments, pump_installations, permits, meters, production, operating_regime, water_samples, profiles, well_id as array, location object, @context). A v1 file containing such fields is malformed.


Deprecation Policy

The .well format evolves in two version dimensions:

  • Major versions (1, 2, 3, …): may remove deprecated fields and introduce breaking changes. Each major version has its own canonical JSON Schema URL.
  • Minor revisions within a major version (2.0, 2.1, …): additive only. Minor revisions may introduce new fields, new vocabulary values, and deprecation markers for existing fields. Minor revisions MUST NOT remove fields, change field semantics, or break round-trip compatibility for files conforming to earlier minor revisions of the same major version.

Field lifecycle

A field moves through three states:

  1. Active — defined and recommended by the current minor revision.
  2. Deprecated — still defined and still valid, but flagged for removal in the next major version. Deprecation is announced in a minor revision (e.g. introduced in v2.0, deprecated in v2.1).
  3. Removed — no longer defined. May only occur in a new major version (e.g. removed in v3.0).

Each deprecation announcement MUST include, in the spec text for the relevant field:

  • The minor revision in which the field was deprecated (e.g. "Deprecated in v2.1").
  • The major version in which the field will be removed (e.g. "Will be removed in v3.0").
  • The replacement field or pattern, when applicable.
  • A v2-to-vNext normalization rule that parsers for the next major version MUST implement to read files using the deprecated field.

Parser behavior

Parsers conformant to the version that introduced a deprecation:

  • MUST accept the deprecated field as valid input.
  • MUST preserve the deprecated field on round-trip unless explicitly migrating the document to a newer version.
  • SHOULD emit a warning when encountering a deprecated field, naming the replacement.
  • MAY offer a migration mode that rewrites the field to its replacement in place. Migration mode MUST be opt-in (e.g. an explicit flag passed to the parser), not the default behavior of read operations.

Parsers for the major version after removal:

  • MUST apply the documented normalization when reading older files (e.g. a v3 parser reading a v2 file that used a v2-deprecated field).
  • MUST NOT accept the removed field name in files declaring the new major version (e.g. a file with version: 3 containing a v2-deprecated field is malformed).

Vocabulary value promotion

When a vocabulary value previously available only with the x- prefix is promoted to canonical (e.g. x-slug_test becomes slug_test):

  • The minor revision that performs the promotion MUST document both forms as equivalent.
  • Parsers from that revision onward MUST treat both forms as equivalent for the remainder of the major version.
  • The x- prefixed form is implicitly deprecated upon promotion and will be removed in the next major version, following the standard field lifecycle.

Canonical deprecation registry

Each minor revision of this spec MUST include a "Deprecations" subsection in its changelog listing all fields and vocabulary values deprecated in that revision, with their replacement and removal timeline. The v2.0 release contains no deprecations.


Top-level Fields

Core identity

FieldTypeRequiredDescription
versioninteger | stringyesFormat version. v2.4 files write "2.4".
well_typestringyesConstruction method of the well. See vocabulary below.
namestringnoWell name or local identifier.
well_drillerstringnoName of the drilling company or individual.
construction_datestringnoISO 8601 calendar date of well completion (YYYY-MM-DD). Date-only by design — time of day for construction completion is not meaningful at the precision the well registry cares about. Interpreted as the local civil date at the well site.
obsstringnoFree-text observations about the well.
well_depthnumbernoThe well's current usable depth in meters from ground level, as measured or reported. May be less than the deepest constructive element (see bore_hole) due to siltation, debris, or partial backfill.

v2 additions

FieldTypeRequiredDescription
@contextstring | array | objectnoJSON-LD context. Reserved field; see § JSON-LD Context.
well_idWellId[]noArray of authority-scoped identifiers. See § well_id.
locationLocationnoGeographic position and elevation. See § location.
profilesstringnoArray of JSON Schema URLs declaring conformance to profiles. See § profiles.

v2.1 additions

FieldTypeRequiredDescription
well_purposestringnoIntended use(s) of the well. See § well_purpose.
centralizersCentralizer[]noCasing/screen centralizers. See object-schemas.md § Centralizer.

v2.3 additions

FieldTypeRequiredDescription
attachmentsAttachment[]noDocuments about the well as a whole, not tied to any record. See object-schemas.md § Attachment.
pump_installationsPumpInstallation[]noPump installation history (installation block). See object-schemas.md § pump_installations[].
permitsPermit[]noLegal instruments governing abstraction (mutable record block). See object-schemas.md § permits[].
metersMeter[]noTotalizer (hidrômetro) installation history (installation block). See object-schemas.md § meters[].
productionProductionEntry[]noLedger of meter readings and declared volumes (ledger block). See object-schemas.md § production[].
operating_regimeOperatingRegime[]noDeclared operating regimes, each in force from effective_from (mutable record block). See object-schemas.md § operating_regime[].
water_samplesWaterSample[]noWater samples and their field and laboratory results (ledger block). See water-quality.md.

Block kinds (since v2.3)

Every top-level array is one of three kinds. The kind decides how records are corrected.

KindBlocksCorrectionEdit tracking
Ledgerhydrodynamic_events, production, water_samplesMAY be edited in place (NOT RECOMMENDED after export). corrects is the recommended mechanism for measurement corrections.updated_at where the block defines it; a corrects entry is the history of a correction.
Mutable recordhistory_logs, permits, operating_regimeEdit in place.updated_at (instant) on the record.
Installationpump_installations, metersEdit in place.updated_at (instant) on the record.

Constructive and geologic arrays describe the well as built and are edited in place. aquifer_analysis entries are interpretations: a new interpretation is a new entry, and earlier ones coexist.

Ledger corrections. A ledger entry referenced by any corrects field is excluded from every derivation but stays in the file. Chains are allowed (C corrects B, which corrected A); only the last uncorrected entry counts. A corrects cycle is malformed and emits a warning. An aquifer_analysis whose source_event_ids or static_level_source_id points to a retracted event emits a warning naming both ids.

Installation pattern. Installation blocks describe equipment present in the well for a period, with installed_at (required) and removed_at (absent means currently installed).

  • removed_at earlier than or equal to installed_at is malformed and emits a warning.
  • Each entry is one installation, not one piece of equipment. A unit pulled and reinstalled gets a new entry with the same serial.
  • Overlapping open installations in the same block emit a warning, not an error. Standby pumps and secondary meters exist.

Naming rules (since v2.3)

  • No unit in a field name. Units are bound by the field-to-unit table (§ Units).
  • flow_rate is the canonical name for a volumetric rate; nameplate values use the rated_ prefix (rated_flow_rate, rated_head, rated_power).
  • from / to are reserved for depth intervals in meters. Time intervals use period_start / period_end.
  • References to another array end in _id (single) or _ids (array), plus the two relationship fields corrects and supersedes.

supersedes vs corrects. supersedes expresses legal succession between two valid permits and appears only on permits. It is not a correction mechanism: corrects retracts ledger entries.


Datetime Conventions

The .well format distinguishes two kinds of temporal values:

Calendar dates — YYYY-MM-DD, no time, no offset. Used for construction_date and, since v2.3, for legal documents: permits[].issued_at, valid_from, valid_until, renewal_requested_at; permits[].conditions[].first_due, last_due; permits[].conditions[].fulfillments[].due_date; and permits[].history[].date, due_date. Interpreted as the local civil date at the well site. Calendar dates are sortable lexicographically and applications MUST NOT attempt to derive an instant from them.

Instants — RFC 3339 datetime strings with a mandatory UTC offset (e.g. 2006-03-14T08:00:00-03:00 or 2006-03-14T11:00:00Z). Used for all event, analysis, and log timestamps:

  • hydrodynamic_events[].datetime
  • aquifer_analysis[].datetime
  • history_logs[].datetime
  • history_logs[].updated_at
  • pump_installations[].installed_at, removed_at, updated_at (since v2.3)
  • permits[].updated_at, permits[].history[].updated_at, permits[].conditions[].fulfillments[].datetime, updated_at (since v2.3)
  • meters[].installed_at, removed_at, updated_at (since v2.3)
  • production[].datetime (meter_reading); production[].period_start, period_end (estimated_volume) (since v2.3)
  • operating_regime[].effective_from, updated_at (since v2.3)
  • water_samples[].datetime, laboratory.received_at, results[].analyzed_at, results[].validation.validated_at (since v2.3)

Validity and deadline checks compare calendar dates, never UTC instants. When an instant is compared with a calendar date — for example a condition fulfillment's datetime against its due_date — the instant's local date is the instant converted to location.properties.timezone (since v2.4). Without timezone, it is the date part of the string, in the offset it carries; producers SHOULD then write such instants in the well site's local offset. A file without timezone whose permits have condition fulfillments emits a warning.

Relative deadlines and recurrences are ISO 8601 date durations (P90D, P6M, P1Y6M); see object-schemas.md § Date duration.

Instants known only by date (since v2.3)

Laboratory reports often give only the date of receipt or analysis. Such an instant is written at 00:00 local time at the well site, and a sibling field named after it with the _resolution suffix is set to "day":

{ "analyzed_at": "2026-09-17T00:00:00-03:00", "analyzed_at_resolution": "day" }
  • Consumers MUST ignore the time of day when _resolution is day. Ordering, holding-time and deadline calculations on that field use day resolution.
  • day is the only allowed value; any other value is malformed. An absent _resolution means the instant is exact.
  • In v2.3 the convention applies to water_samples[].laboratory.received_at and water_samples[].results[].analyzed_at. It is the candidate general convention for any instant known only by its date.

A datetime without an offset (naked YYYY-MM-DDTHH:MM:SS) is malformed and parsers MUST reject it. Time zone abbreviations (EST, BRT) are not RFC 3339 and MUST NOT be used.

Ordering and ties

Instants are ordered by absolute UTC instant, not by the lexical form of the string. The strings 2006-03-14T08:00:00-03:00 and 2006-03-14T11:00:00Z represent the same instant and tie for ordering purposes.

When two events share the same instant, the optional sequence integer breaks the tie (lower values sort first). When two events share the same instant and no sequence is provided, ordering is implementation-defined; producers SHOULD provide sequence when authoring events with identical instants.


Many string fields are open: they accept any value, but recommend a vocabulary for interoperability. The sections below list each one. Non-canonical values SHOULD use the x- prefix, and tools MUST preserve unrecognized values and display them as-is.

Every recommended vocabulary is also published as data by @welldot/core (e.g. PERMIT_TYPES, CONSTRUCTION_MATERIALS, SAMPLE_TYPES), each entry carrying its value and display labels keyed by BCP 47 language tag (at least en and pt). The field types use the OpenVocab<T> pattern (T | (string & {})): the recommended values are typed while any other string stays valid. The Portuguese column in the tables below may be more descriptive than the short display label.

The well_type field accepts any string and describes the well's construction method. The values below are the recommended vocabulary for interoperability. Tools should treat unrecognized values gracefully.

ValuePortuguese (BR)Description
tubularTubularConventional rotary or percussion drilled well
hand_dugCacimba / poço escavadoManually excavated well or cistern
horizontalHorizontalHorizontal or sub-horizontal well
infiltration_galleryGaleria de infiltraçãoHorizontal subsurface infiltration gallery
artesianArtesianoDeprecated in v2.1 — see below

Non-canonical values SHOULD use the x- prefix (e.g. x-radial_collector).

artesian (deprecated in v2.1, removal in v3). Artesianism is a hydraulic condition, not a construction method: an artesian well is usually a tubular well. A flowing artesian condition is recorded as a hydrodynamic_events entry whose static_level is negative (see § Level sign convention), and applications derive the label from it. Parsers MUST continue to accept well_type: "artesian" and MUST NOT rewrite it. Authoring tools SHOULD offer to migrate it to the actual construction method on edit.


well_purpose is an optional array of strings giving the well's current intended use(s). A well may have more than one purpose (e.g. ["production", "monitoring"]). Changes of use over time belong in history_logs (category event). Non-canonical values SHOULD use the x- prefix.

ValuePortuguese (BR)Description
productionProdução / captaçãoWater supply abstraction
monitoringPoço de monitoramentoGroundwater level and/or quality monitoring
piezometerPiezômetroMeasures hydraulic head at a discrete depth interval
water_level_indicatorINA — indicador de nível d'águaOpen standpipe for water table readings (typically geotechnical)
observationPoço de observaçãoObservation well for aquifer tests on a nearby pumping well
explorationPesquisa / exploratórioInvestigation or test well
injectionInjeção / recargaManaged aquifer recharge or injection
dewateringRebaixamentoConstruction or mining dewatering

ValueEnglishPortuguese (BR)
rotaryRotaryRotativo
percussionPercussionPercussão
cable_toolCable toolPercussão a cabo
augerAugerTrado
air_hammerAir hammerMartelo pneumático

Non-canonical values SHOULD use the x- prefix.

Shared by well_case[].type, well_screen[].type, reduction[].type and pump_installations[].riser_material.

ValueEnglishPortuguese (BR)
pvcPVCPVC
geomechanical_pvcGeomechanical PVCPVC geomecânico
carbon_steelCarbon steelAço carbono
galvanized_steelGalvanized steelAço galvanizado
stainless_steelStainless steelAço inox
fiberglassFiberglassFibra de vidro

Non-canonical values SHOULD use the x- prefix.

The screen design, independent of its material (well_screen[].type).

ValueEnglishPortuguese (BR)
continuous_slotContinuous slotEspiralado (tipo Johnson)
slottedSlottedRanhurado
bridge_slotBridge slotTipo ponte
louverLouverVeneziana
perforatedPerforatedPerfurado
noldNold typeTipo Nold

continuous_slot is the wire-wrapped (wire-wound) screen. nold is the steel screen sold under that trade designation (filtro tipo Nold). Non-canonical values SHOULD use the x- prefix.

ValueEnglishPortuguese (BR)
spring_bowSpring bowMola (spring bow)
rigidRigidRígido
semi_rigidSemi-rigidSemirrígido
polymerPolymerPolimérico
carbon_steelCarbon steelAço carbono
galvanized_steelGalvanized steelAço galvanizado
stainless_steelStainless steelAço inox

The steel values name rigid centralizers by their material. Non-canonical values SHOULD use the x- prefix.

ValueEnglishPortuguese (BR)
concreteConcreteConcreto
reinforced_concreteReinforced concreteConcreto armado
cementCementCimento
mortarMortarArgamassa

type describes the pad material; other free text (e.g. a shape) remains valid.


ValuePortuguese (BR)Description
submersibleBomba submersaElectric submersible pump.
vertical_turbineBomba de eixo verticalSurface motor with line shaft.
jetBomba injetoraSurface jet pump.
progressive_cavityBomba helicoidalProgressive cavity pump, common with solar power.
hand_pumpBomba manual
compressor_airliftCompressor (air-lift)Permanent airlift production.

Solar is a power_source, never a type. Non-canonical values SHOULD use the x- prefix.

ValuePortuguese (BR)
gridRede elétrica
solarSolar (fotovoltaico)
dieselGerador a diesel
hybridHíbrido
ValuePortuguese (BR)Description
abstraction_permitOutorga de direito de usoGrant to abstract groundwater.
preliminary_permitOutorga prévia / declaração de reservaPermission before drilling.
exemptionDispensa / uso insignificanteFormal exemption for small users.
registrationCadastro (e.g. CNARH)Registration without a grant.
dewatering_permitOutorga para rebaixamentoMining and construction dewatering.
drilling_permitAutorização de perfuraçãoAuthorization to drill the well.

renewal is not a type: a renewal is a new permit of the same type whose supersedes points to the previous one. Non-canonical values SHOULD use the x- prefix.

ValuePortuguese (BR)
human_supplyAbastecimento público / consumo humano
industrialIndustrial
miningMineração
irrigationIrrigação
livestockDessedentação animal
commercialComercial / serviços

water_use describes what the abstracted water is for; well_purpose describes the well's role.

ValuePortuguese (BR)Covers
monitoringMonitoramentoWater level, flow, abstracted volume and water quality monitoring/sampling
reportingRelatórios e declaraçõesPeriodic reports and volume/flow declarations submitted to the authority
equipment_installationInstalação de equipamentosMeters (hidrômetro), level gauges, sampling taps, telemetry
well_protectionProteção do poçoSanitary slab, seal, protection perimeter, wellhead closure
environmentalAmbientalEnvironmental measures, compensation, licensing of the activity
legalLegal / administrativoRenewal request, fees, registrations, document submissions

Non-canonical values SHOULD use the x- prefix.

ValuePortuguese (BR)
filingProtocolo / requerimento
processAndamento do processo / despacho
notificationNotificação / ofício
feeTaxa / emolumento
inspectionVistoria
decisionDecisão / publicação
renewalRenovação

Non-canonical values SHOULD use the x- prefix. The administrative status of a permit is a closed vocabulary; see object-schemas.md § permits[] — Administrative status.

ValuePortuguese (BR)
mechanicalHidrômetro mecânico
electromagneticMedidor eletromagnético
ultrasonicMedidor ultrassônico

Non-canonical values SHOULD use the x- prefix.

type — the entry discriminator: meter_reading (a totalizer register value) or estimated_volume (a volume estimated for a period, without a meter). Non-canonical entry types SHOULD use the x- prefix; parsers preserve them and exclude them from volume derivations.

source (meter_reading):

ValuePortuguese (BR)
manualLeitura manual
telemetryTelemetria

method (estimated_volume) — the basis of the estimate. Descriptive only: it never changes how the volume is counted.

ValuePortuguese (BR)Description
flow_timeVazão × tempo de operaçãoFlow rate times operating time (hour meter, operating regime).
energyConsumo de energiaDerived from the pump's energy consumption.
user_statementInformado pelo usuárioStated by the owner or operator, without a documented calculation.

Recommended values for sample_type, sampling_method, sampling_point.type and sampling_point.device are listed in water-quality.md § Recommended values.

Used by spot_measurement and logger_series (since v2.4) events.

ValueEnglishPortuguese (BR)
electric_probeElectric probeSonda elétrica
pressure_transducerPressure transducerTransdutor de pressão
air_lineAir lineLinha de ar
tapeTapeTrena

Non-canonical values SHOULD use the x- prefix.

ValueEnglishPortuguese (BR)
cooper_jacobCooper-JacobCooper-Jacob
theisTheisTheis
neumanNeumanNeuman
hantushHantushHantush
birsoy_summersBirsoy-SummersBirsoy-Summers
eden_hazelEden-HazelEden-Hazel
visual_inspectionVisual inspectionInspeção visual

Non-canonical values SHOULD use the x- prefix.

ValuePortuguese (BR)Category-specific fields
maintenanceManutençãomaintenance_type, pump_installation_id, meter_id (since v2.3)
inspectionInspeção—
incidentIncidente—
eventEvento—
status_changeMudança de situaçãostatus (since v2.3)

Descriptions are in object-schemas.md § history_logs[]. Category-specific fields MUST be absent on entries of other categories; their presence emits a warning. Non-canonical values SHOULD use the x- prefix.

ValueEnglishPortuguese (BR)
lowLowBaixa
mediumMediumMédia
highHighAlta
criticalCriticalCrítica

Non-canonical values SHOULD use the x- prefix.

ValuePortuguese (BR)
inspectionInspeção
cleaningLimpeza
redevelopmentRedesenvolvimento
disinfectionDesinfecção
pump_serviceManutenção da bomba
meter_calibrationAferição do hidrômetro
video_inspectionFilmagem / perfilagem ótica
level_measurementMedição de nível
pump_testTeste de bombeamento
water_samplingColeta de água

Non-canonical values SHOULD use the x- prefix.

history_logs[].status — Allowed values (since v2.3)

Used by entries of category status_change. This is a closed vocabulary: status MUST be one of the five values below. Any other value, including an x- value, is a schema error and the file is rejected.

ValuePortuguese (BR)Semantics
activeAtivo / em operaçãoNormal operation.
maintenanceEm manutençãoTemporarily out of service for work.
inactiveParalisadoOut of service, recoverable.
decommissionedDesativado / tamponadoPermanently closed and properly sealed.
abandonedAbandonadoLeft without proper sealing.

The well's current status is the status of the status_change entry with the latest datetime; with no such entry, the status is unknown.

ValuePortuguese (BR)Typical location
drilling_reportRelatório de perfuração / relatório técnicoRoot
as_built_drawingPerfil construtivo as-builtRoot
registry_recordFicha cadastral (SIAGAS, CNARH)Root
photoFotografiaAny
permit_documentPortaria / certificado de outorgapermits
condition_evidenceComprovante de cumprimento de condicionantepermits[].conditions[].fulfillments
pump_curveCurva da bombapump_installations
field_sheetPlanilha de campohydrodynamic_events
test_reportRelatório de teste de bombeamentoaquifer_analysis
lab_reportLaudo laboratorialwater_samples
invoiceNota fiscalAny

The vocabulary is open; non-canonical values SHOULD use the x- prefix.


well_id

Array of authority-scoped identifiers linking the well to external registries. A well may be registered in multiple national, regional, or institutional registries simultaneously.

FieldTypeRequiredDescription
authoritystringyesName of the issuing registry or institution (e.g. "SIAGAS", "ANA", "NGWD").
idstringyesThe identifier as issued by the authority.
primarybooleannoMarks the canonical identifier. At most one entry may have primary: true.

Producers SHOULD mark exactly one entry primary: true. The rule "the first entry is canonical" applies only as a fallback when no entry is marked, because it is fragile when the order changes. Parsers MUST warn when multiple entries have primary: true.

Numeric ID conversion

All id values are strings. When the source identifier from an external system is an integer, the string representation MUST be the canonical base-10 representation with no leading zeros, no thousands separator, and no locale-specific formatting. The integer 42 becomes "42", not "042" or "42,".

When the source identifier is a fixed-width string with significant leading zeros (e.g. "00042819" from a registry where width carries meaning), the original string MUST be preserved verbatim. Composite identifiers containing significant leading zeros in their numeric portion (e.g. SIAGAS "SP-0042819") MUST be preserved as-is.

Uniqueness

The combination (authority, id) MUST be unique within the well_id array. See § Cross-reference and uniqueness rules for the duplicate-handling policy.

"well_id": [
  { "authority": "SIAGAS", "id": "SP-0042819", "primary": true },
  { "authority": "ANA",    "id": "02000.001234/2006-78" },
  { "authority": "utility-internal", "id": "PP-01" }
]

location

Geographic position and elevation of the wellhead. Supersedes the v1 top-level lat, lng, and elevation fields.

The three primary measurements — lat, lng, elevation — are top-level fields on the location object for ergonomics. All ancillary metadata (datum, CRS, precision, source CRS) lives under a nested properties object.

FieldTypeRequiredDescription
latnumberyesLatitude in decimal degrees.
lngnumberyesLongitude in decimal degrees.
elevationnumbernoWellhead elevation in meters above the WGS84 reference ellipsoid (or the datum named in properties.elevation_datum).
propertiesLocationPropertiesnoAncillary metadata. When absent, all defaults apply.

LocationProperties

FieldTypeRequiredDescription
elevation_datumstringnoReference datum for elevation. See vocabulary below. Default: wgs84_ellipsoid.
crsstringnoEPSG code of the coordinate reference system. Must be a geographic (not projected) CRS. Default: "EPSG:4326" (WGS84).
lat_precisionnumbernoOne-sigma precision of lat in decimal degrees.
lng_precisionnumbernoOne-sigma precision of lng in decimal degrees.
elevation_precisionnumbernoOne-sigma precision of elevation in meters.
original_crsstringnoEPSG code of the source CRS, preserved for traceability when source data was in a projected CRS that the converter transformed to geographic. Informational only.
timezonestringnoIANA time zone of the well site (e.g. America/Belem). A value that is not a valid IANA name is malformed. (since v2.4)
ValueDescription
wgs84_ellipsoidWGS84 reference ellipsoidal height. Default.
egm2008Earth Gravitational Model 2008 geoid
egm96Earth Gravitational Model 1996 geoid
local_mslLocal mean sea level (imprecise; specific datum SHOULD be named via x- prefix, e.g. x-imbituba for Brazil's national vertical reference)

When elevation_datum is omitted, parsers MUST assume wgs84_ellipsoid.

CRS scope

Only geographic coordinate reference systems are permitted in properties.crs. Projected CRS values (e.g. UTM zones) are not valid. If source data uses a projected CRS, the converting application MUST transform to geographic coordinates before writing the file. The original_crs field MAY be populated with the source CRS for traceability.

"location": {
  "lat": -1.4558,
  "lng": -48.5039,
  "elevation": 12.5,
  "properties": {
    "elevation_datum": "wgs84_ellipsoid",
    "crs": "EPSG:4326",
    "lat_precision": 0.0001,
    "lng_precision": 0.0001,
    "elevation_precision": 0.5,
    "original_crs": "EPSG:31983"
  }
}

Units

All numeric values in a .well file are in SI. The format does not encode unit declarations; the units below are the single, canonical interpretation for every field of the corresponding kind. No file may override these.

Canonical units

QuantityUnitUCUMStored as
Depth, length, elevationmetermnumber
Diametermillimetermmnumber
Volumetric flow ratecubic meter per hourm3/hnumber
Elapsed time, durationminuteminnumber
Daily operating timehourhnumber (above 24 read as 24)
Volumecubic meterm3number
PowerkilowattkWnumber
VoltagevoltVnumber
Cross-sectional areasquare millimetermm2number
Mass concentrationmilligram per litermg/Lnumber (since v2.3)
Electrical conductivitymicrosiemens per centimeter at 25 °CuS/cmnumber (since v2.3)
Temperaturedegree CelsiusCelnumber (since v2.3)
Redox potentialmillivoltmVnumber (since v2.3)
TurbidityNTU, FNU, FAU, FTU (by parameter code)—number (since v2.3)
ColorHazen unit (uH = mg Pt-Co/L)—number (since v2.3)
Microbiological countMPN/100 mL, CFU/100 mL, CFU/mL (by parameter code){MPN}/(100.mL), {CFU}/(100.mL), {CFU}/mLnumber (since v2.3)
Activity concentrationbecquerel per literBq/Lnumber (since v2.3)
Filter pore sizemicrometerumnumber (since v2.3)
Transmissivitysquare meter per secondm2/snumber
Hydraulic conductivitymeter per secondm/snumber
PressurekilopascalkPanumber
Angle (azimuth, dip)degreedegnumber (0–360 for azimuth, 0–90 for dip)
Geographic coordinatesdecimal degree (WGS84)degnumber
Calendar dateISO 8601—string YYYY-MM-DD
InstantRFC 3339 with UTC offset—string

UCUM is the Unified Code for Units of Measure, the international machine-parseable unit standard used by OGC SWE and the scientific community. The UCUM column above documents the canonical encoding of each unit for use in JSON-LD contexts, profile schemas, and downstream interoperability — it is not encoded in .well files themselves.

Field-to-unit binding (normative)

Meter (m) — all depths, lengths, and elevations:

  • well_depth
  • bore_hole[].from, bore_hole[].to
  • well_case[].from, well_case[].to
  • reduction[].from, reduction[].to
  • well_screen[].from, well_screen[].to
  • surface_case[].from, surface_case[].to
  • hole_fill[].from, hole_fill[].to
  • centralizers[].from, centralizers[].to, centralizers[].spacing
  • cement_pad.width, cement_pad.length, cement_pad.thickness
  • lithology[].from, lithology[].to
  • fractures[].depth, fractures[].depth_precision
  • caves[].from, caves[].to
  • hydrodynamic_events[].static_level, static_level_precision
  • PumpingStep.readings[].depth, depth_precision
  • RecoveryPhase.readings[].depth, depth_precision
  • logger_series.sensor_depth, readings[].depth, depth_precision, depth_min, depth_max (since v2.4)
  • aquifer_analysis[].static_level, static_level_precision
  • aquifer_analysis[].dynamic_level, dynamic_level_precision
  • aquifer_analysis[].aquifer_thickness
  • location.elevation, location.properties.elevation_precision
  • pump_installations[].intake_depth, rated_head, electrical.cable_length (since v2.3)
  • water_samples[].sampling_point.depth, depth_precision, from, to (since v2.3)

Millimeter (mm) — all diameters and slot openings:

  • bore_hole[].diameter
  • well_case[].diameter
  • reduction[].diam_from, reduction[].diam_to
  • well_screen[].diameter, well_screen[].screen_slot
  • surface_case[].diameter
  • hole_fill[].diameter
  • centralizers[].diameter
  • pump_installations[].riser_diameter (since v2.3)
  • meters[].nominal_diameter (since v2.3)

Cubic meter per hour (m3/h) — all volumetric flow rates:

  • PumpingStep.rate, rate_precision
  • aquifer_analysis[].flow_rate, flow_rate_precision
  • recovery_only.pumping_rate
  • pump_installations[].rated_flow_rate (since v2.3)
  • permits[].flow_rate, permits[].monthly_schedule[].flow_rate (since v2.3)
  • operating_regime[].flow_rate (since v2.3)
  • water_samples[].purge.flow_rate (since v2.3)

Minute (min) — all elapsed times and durations:

  • PumpingStep.duration
  • LevelReading.elapsed
  • recovery_only.pumping_duration
  • logger_series.interval (since v2.4)
  • water_samples[].purge.duration, purge.readings[].elapsed (since v2.3)

Cubic meter (m3) — volume (since v2.3):

  • permits[].volume_limits[].volume
  • meters[].max_reading
  • production[].reading (meter_reading), production[].volume (estimated_volume)
  • water_samples[].purge.volume

Hour (h) — daily operating time (since v2.3):

  • permits[].daily_operating_time, permits[].monthly_schedule[].daily_operating_time
  • operating_regime[].daily_operating_time

The minute remains the canonical unit for elapsed time and durations. The hour is bound only to daily_operating_time, which regulators always express in hours.

Square meter per second (m2/s) — transmissivity:

  • aquifer_analysis[].transmissivity

Meter per second (m/s) — hydraulic conductivity:

  • aquifer_analysis[].hydraulic_conductivity

Kilopascal (kPa) — pressure:

  • LevelReading.pressure

Kilowatt (kW) — power (since v2.3):

  • pump_installations[].rated_power

Volt (V) — voltage (since v2.3):

  • pump_installations[].electrical.voltage

Square millimeter (mm2) — cross-sectional area (since v2.3):

  • pump_installations[].electrical.cable_section

Degree Celsius (Cel) — temperature (since v2.3):

  • water_samples[].laboratory.received_temperature

Micrometer (um) — filter pore size (since v2.3):

  • water_samples[].results[].filtration.pore_size

Unit by parameter code (since v2.3) — water_samples[].results[].value, detection_limit, quantification_limit, value_precision and purge.readings[].value are in the canonical unit of the result's parameter (see water-quality.md § Units).

Degree (deg) — angles and geographic coordinates:

  • fractures[].azimuth, fractures[].dip
  • location.lat, location.lng, location.properties.lat_precision, location.properties.lng_precision

Unitless — dimensionless or domain-specific values:

  • aquifer_analysis[].storativity (dimensionless)
  • aquifer_analysis[].jacob_b, jacob_c (composite units; treated as the units required to make the standard Jacob equation balance with stored flow_rate and length)
  • aquifer_analysis[].well_efficiency_pct (percentage, 0–100)
  • aquifer_analysis[].specific_capacity (derived ratio in m³/h per m, i.e. m2/h)
  • Lithology color (CSS hex string)
  • pump_installations[].stages, electrical.phases (counts)
  • permits[].monthly_schedule[].month, days; permits[].conditions[].occurrences (counts)
  • operating_regime[].days_per_week (count, 1–7)

Water quality units (since v2.3)

Water quality results take their unit from the parameter code; only x- vocabulary codes declare unit (UCUM). The unit-by-code rule and regional unit normalization are specified in water-quality.md § Units.

Level sign convention

Depths are measured from ground level (0) and increase downward. Water levels above ground level are therefore negative. This applies to static_level, LevelReading.depth, and aquifer_analysis[].static_level / dynamic_level. A negative static level is how a flowing artesian condition is recorded (see § well_type). This convention was implicit in v2.0 and is made explicit in v2.1 without changing semantics. It does not apply to pump_installations[].intake_depth, which is an equipment depth and is always positive.

Diameter and the as-built convention

Diameters in casing, screens, surface case, and hole fill are stored as the as-built outer diameter in millimeters, not as nominal manufacturer designations. A casing sold as "6 inch" with a real outer diameter of 168.3 mm is recorded as 168.3, not 152.4 (the literal conversion of 6 inches to mm). Nominal-to-actual mapping for common pipe and screen sizes is a market convention handled by applications — typically by the converter or input form — not by the file format.

Screen slot

well_screen[].screen_slot is in millimeters like every other diameter field. US-market slot-number designations (e.g. "20 slot" = 0.020 inch = 0.508 mm) are an input convenience handled by applications, not encoded in the file. The v1 field name screen_slot_mm was a legacy artifact and is renamed to screen_slot in v2; the value is in millimeters before and after.

Rationale

An interchange format with configurable units multiplies the number of valid encodings of the same well, complicates equality and comparison, and introduces a class of bugs where the declared units do not match the stored values. The .well format is designed to be a canonical machine representation: one well, one encoding. Display units, input units, and locale-specific notation are concerns of the applications that read and write .well files, not of the format itself. This separation matches the design of GeoJSON (WGS84 only), RFC 3339 (UTC offsets always present), and most modern interchange formats.

Producers receiving non-SI source data (imperial drilling reports, US gpm flow measurements, inch casing designations, slot-number screens) MUST convert to SI before writing. Consumers presenting the data to users in non-SI units MUST convert on read.

Conversion utilities for the common transformations are provided in @welldot/core under the units module — m ↔ ft, mm ↔ in, m³/h ↔ L/s, m³/h ↔ US gpm, m²/s ↔ m²/d, DD ↔ DMS, slot-number ↔ mm, cv/hp ↔ kW, L / ft³ / US gal ↔ m³, µg/L ↔ mg/L, mS/m ↔ µS/cm, and similar.


Water quality parameter vocabulary (since v2.3)

The welldot parameter vocabulary (98 codes), its rules, the CAS equivalences and the treatment of limit sets are specified in water-quality.md § Parameter vocabulary.


profiles

An optional array of HTTPS URLs declaring formal extensions to the spec that the file conforms to. Each URL MUST resolve to a JSON Schema document.

"profiles": [
  "https://welldot.org/profiles/brazil-ana/v1/schema.json",
  "https://inspire.ec.europa.eu/schemas/gwhyd/4.0/profile.json"
]

Profile schema requirements

  • Each URL MUST be an HTTPS URL resolving to a JSON Schema document (Content-Type: application/schema+json or application/json).
  • The schema SHOULD extend the canonical .well v2 schema via allOf + $ref, but this is not required.
  • The schema MAY link to human documentation via its description field or a custom x-documentation field pointing to a Markdown or PDF URL.
  • Profiles MAY impose additional required fields, constrain vocabulary values, or mandate the use of specific x- extensions for a regulatory context.

Example: a regulatory water quality profile (since v2.3)

See water-quality.md § Regulatory profiles.

Profile validation

  • If a profile URL is unreachable, returns a non-JSON document, or fails to parse as JSON Schema, the profile is silently ignored. Parsers MUST NOT reject files whose profile URLs are unavailable.
  • A profile-aware parser SHOULD validate the file against each reachable profile schema and surface failures as warnings, not errors. Conformance is asserted by the author, not enforced by the spec.
  • Profile URLs SHOULD be versioned via path segments or schema-internal $id to ensure stability.

Extensibility

Custom fields — x- prefix

Any implementer may add custom fields to any object by prefixing the field name with x-. This convention is established by OpenAPI 3.x and JSON Schema. Parsers MUST preserve and ignore x- fields they do not recognize. Sub-properties within an x- object do not need to be prefixed. For application extensions, x-<vendor>-<name> is RECOMMENDED (e.g. x-welldot-custom), so tools that both use x-custom do not collide. (since v2.4)

{
  "id": "b2c3d4e5-...",
  "type": "constant_rate",
  "datetime": "2006-03-14T08:00:00-03:00",
  "x-siagas": {
    "registro": "SP-0042819",
    "processo_ana": "02000.001234/2006-78"
  }
}

Fields without the x- prefix that are not defined in this spec are technically non-conformant. Parsers MUST NOT reject such files but SHOULD emit a warning.

Custom top-level blocks — x- prefix required

Top-level blocks not defined in this spec MUST use the x- prefix. For application extensions, x-<vendor>-<name> is RECOMMENDED (e.g. x-welldot-custom), so tools that both use x-custom do not collide. (since v2.4) Parsers MUST preserve and ignore unrecognized top-level keys.

{
  "version": "2.4",
  "x-gas_monitoring": [ ... ],
  "x-geophysical_logs": [ ... ]
}

Custom vocabulary values — x- prefix

Open vocabulary fields in this spec (type in hydrodynamic_events, category in history_logs, vocabulary in texture and in water quality parameter (as x-… vocabularies), method in aquifer_analysis, well_type, and any other field documented as accepting any string; not closed vocabularies such as history_logs[].status) SHOULD use the x- prefix when the value is non-canonical — i.e. not listed in the recommended vocabulary of this spec.

Parsers MUST treat x- prefixed vocabulary values as valid. Promotion from x- form to canonical form follows the Deprecation Policy (see § Deprecation Policy — Vocabulary value promotion).

{ "type": "x-slug_test" }
{ "category": "x-site_visit" }
{ "method": "x-theis_recovery" }

Offline packaging (since v2.4)

A .well file references its attachments by absolute URL, and HTTPS links may expire. For regulators and long-term archiving, a .well file MAY be delivered as an offline package: a ZIP archive with the extension .wellz.

  • The .well file sits at the archive root, and the attachments sit at relative paths inside the archive.
  • In this mode an Attachment.uri MAY be a relative path to the file inside the archive, and sha256 is required.
  • Outside a package, uri stays an absolute URL. A relative uri in a bare .well file is not valid.

The package is a delivery wrapper, not a second format: the .well file inside it is an ordinary .well file. Validators and parsers read the .well alone, so the schema keeps uri as a URL; resolving relative paths and checking sha256 is the job of the tool that opens the package.


Cross-reference and Uniqueness Rules

The .well format uses string IDs to link records across arrays. This section is the single normative source for ID semantics.

Uniqueness scope

Each ID-bearing array maintains its own uniqueness scope. The ID namespaces are independent:

  • hydrodynamic_events[].id — unique within hydrodynamic_events
  • aquifer_analysis[].id — unique within aquifer_analysis
  • history_logs[].id — unique within history_logs
  • pump_installations[].id — unique within pump_installations (since v2.3)
  • permits[].id — unique within permits (since v2.3)
  • permits[].conditions[].id — unique within the conditions array of one permit (since v2.3)
  • permits[].conditions[].fulfillments[].id — unique within the fulfillments array of one condition (since v2.3)
  • permits[].history[].id — unique within the history array of one permit (since v2.3)
  • permits[].monthly_schedule[].month and permits[].volume_limits[].period — unique within one permit (since v2.3)
  • meters[].id — unique within meters (since v2.3)
  • production[].id — unique within production (since v2.3)
  • operating_regime[].id — unique within operating_regime (since v2.3). operating_regime[].effective_from is not unique: duplicates are a warning (since v2.4)
  • water_samples[].id — unique within water_samples (since v2.3)
  • attachments[].id — unique within its owning array: the root attachments, or the attachments array of one record (history_logs, permits, permits[].history, permits[].conditions[].fulfillments, pump_installations, meters, hydrodynamic_events, aquifer_analysis, water_samples). The same id may appear under different records.
  • well_id[] — uniqueness is on the composite key (authority, id), not on id alone

An ID value MAY repeat across different arrays without conflict (e.g. an event and an analysis MAY both use the ID "001"), though distinct values are recommended for clarity.

Cross-array references

The following fields hold references to IDs in other arrays:

Reference fieldPoints toResolution scope
aquifer_analysis[].source_event_ids[]hydrodynamic_events[].idSame file only
aquifer_analysis[].static_level_source_idhydrodynamic_events[].idSame file only
hydrodynamic_events[].correctshydrodynamic_events[].idSame file only
production[].correctsproduction[].idSame file only
production[].meter_idmeters[].idSame file only
permits[].supersedespermits[].idSame file only
history_logs[].pump_installation_idpump_installations[].idSame file only
history_logs[].meter_idmeters[].idSame file only
history_logs[].hydrodynamic_event_ids[]hydrodynamic_events[].idSame file only
history_logs[].sample_ids[]water_samples[].idSame file only
permits[].conditions[].fulfillments[].event_idhydrodynamic_events[].idSame file only
permits[].conditions[].fulfillments[].sample_idwater_samples[].idSame file only
water_samples[].correctswater_samples[].idSame file only
water_samples[].parent_sample_idwater_samples[].idSame file only
water_samples[].static_level_event_idhydrodynamic_events[].idSame file only
water_samples[].sampling_point.pump_installation_idpump_installations[].idSame file only

Root attachments is not a registry: records never reference root attachments by id. Nor is it an aggregate: it holds only general files about the well as a whole (e.g. the drilling report), never copies of the attachments of history_logs, permits (including their history entries and condition fulfillments), pump_installations, meters, hydrodynamic_events, aquifer_analysis or water_samples entries. A document that concerns several records is repeated on each; sha256 guarantees both copies point to the same file.

Cross-file references are not supported in v2.

Dangling references

A dangling reference is a reference field whose value does not match any ID in the target array.

  • Dangling references MUST emit a warning naming the referring field, the referring object's ID, and the missing target ID.
  • Dangling references MUST NOT cause file rejection. Events may be legitimately deleted from history (regulatory retention rules, GDPR-style erasure) leaving analyses that reference them stranded.
  • Consumers MUST preserve unresolved references when re-exporting and MUST NOT remove them silently. Removing a reference is always a deliberate user action, never a side effect of import or export. (since v2.4)

Repeated records (since v2.4)

Collective permits and campaign blanks apply to several wells, so they are repeated in each well's file.

  • Copies MUST share the same id and SHOULD have identical content.
  • Consumers MAY merge copies by id.
  • A fulfillment's event_id or sample_id resolves only in the file of the well that produced it. In the other copies it is an expected unresolved reference and emits no warning.

Duplicate IDs within a scope

A duplicate ID occurs when two records in the same uniqueness scope share the same ID (or, for well_id, the same (authority, id) pair).

Duplicate IDs are malformed but recoverable:

  • Parsers MUST NOT silently accept duplicate IDs. The file is considered malformed.
  • Parsers MUST NOT silently rewrite duplicate IDs. Automatic renaming would change the object graph in a way that downstream references cannot detect.
  • Interactive applications MUST surface the duplication to the user with sufficient context to decide:
    • The IDs in conflict
    • A summary of each conflicting record (datetime, type, key fields)
    • The choices: merge (keep one, discard the other), rename (assign a new ID to one of them, updating any references in the same file), or abort load.
  • Non-interactive parsers (batch importers, server-side validators) MUST reject the file with a clear error rather than guess.
  • Any user-confirmed resolution MUST be logged as a history_logs entry with category: "event" describing what was changed.

The objective is deterministic load behavior: a .well file MUST produce the same object graph across all conformant parsers under default settings. User-mediated repair is the only path that can deviate from this, and it must be explicit.

id field convention

All id fields are string type. UUID v4 is recommended for new records. Sequential strings (e.g. "evt-001") are valid for manually authored files. Numeric IDs from external systems are converted per the rule documented in § well_id (Numeric ID conversion).


Precision and Uncertainty

Optional one-sigma precision qualifiers are defined for the most consequential measurement fields. Parsers that do not recognize them ignore them per the foreign-members rule.

The precision field name is the measurement field name suffixed with _precision. The unit of the precision value is the unit of the measurement it qualifies.

Supported precision fields

MeasurementPrecision fieldDefined on
latlat_precisionLocationProperties
lnglng_precisionLocationProperties
elevationelevation_precisionLocationProperties
static_levelstatic_level_precisionevents, AquiferAnalysis
dynamic_leveldynamic_level_precisionAquiferAnalysis
depthdepth_precisionLevelReading, Fracture
raterate_precisionPumpingStep
flow_rateflow_rate_precisionAquiferAnalysis
depthdepth_precisionSamplingPoint (since v2.3)
valuevalue_precisionwater quality Result (since v2.3)

All precision fields are optional. When omitted, the measurement value carries no documented precision. Precision is the one-sigma standard deviation in the same unit as the measurement.

Laboratory reports usually give an expanded uncertainty U with a coverage factor k (typically k = 2). Converters store value_precision = U / k, never U itself.

{ "depth": 44.8, "depth_precision": 0.01 }

.well Format Specification v2.4