Skip to content

Data Format

Correlate stores everything in a single JSON file called correlate.json. If you have sync enabled, that same file is what's pushed to your iCloud or WebDAV server. You can also export a copy any time from Settings → Your DataExport.

This page is a reference for that file's structure — useful if you want to back it up, write your own tools, or import data from somewhere else.

High-level shape

{
  "schemaVersion": 3,
  "dataId": "<UUID>",
  "lastModified": "2026-05-03T07:42:11Z",
  "variables": [ ... ],
  "entries": { ... },
  "savedSearches": [ ... ],
  "savedReports": [ ... ]
}
  • schemaVersion — integer indicating which version of this file format wrote the document. The current version is 3. See Schema versioning below.
  • dataId — a stable UUID that identifies this dataset's lineage. Used during sync to detect when two devices have unrelated data.
  • lastModified — ISO-8601 timestamp of the most recent change. Used to pick the newer side during sync.
  • variables — the full list of variable definitions, including any you've deleted (deleted variables are kept so historical entries that reference them remain interpretable).
  • entries — a dictionary keyed by date in YYYY-MM-DD form. Each entry holds the day's variable values and an optional note.
  • savedSearches — your saved searches, stored alongside the data so they sync to your other devices.
  • savedReports — your saved reports, same idea.

Schema versioning New in 2.8

The data file carries an explicit schemaVersion so different builds of Correlate can tell which fields they should expect. The rules:

  • A file with no schemaVersion is treated as schema 1 (older files written before the field existed).
  • A file with a schemaVersion the running build doesn't know how to read is rejected outright — the app refuses to overwrite your local data, and sync refuses to pull or push from a remote on a newer schema. This is a deliberate safety net so an older build can't silently drop fields it doesn't recognize.
  • When a newer version of Correlate raises the current schemaVersion, it ships with migration code that upgrades older files in place the first time they're loaded.

In practice this means: if you sync between devices, keep them on the same release (or at least don't downgrade one of them). If you mix versions, sync will surface the mismatch instead of silently corrupting either side.

A small example

{
  "dataId": "f8a3c2b1-1234-4abc-9def-0123456789ab",
  "lastModified": "2026-05-03T07:42:11Z",
  "variables": [
    {
      "id": "a1...",
      "name": "Sleep",
      "note": "In hours, scaled by quality",
      "sortOrder": 0,
      "isDeleted": false,
      "type": {
        "float": { "min": 5, "max": 10, "precision": 1 }
      }
    },
    {
      "id": "b2...",
      "name": "Gym visit",
      "note": "Or at least an hour of effort",
      "sortOrder": 1,
      "isDeleted": false,
      "type": {
        "boolean": {}
      }
    }
  ],
  "entries": {
    "2026-03-22": {
      "values": {
        "a1...": { "floatValue": 7.5 },
        "b2...": { "boolValue": true }
      },
      "note": "Felt good. Long run in the morning."
    }
  },
  "savedSearches": [],
  "savedReports": []
}

Notes on each piece

  • A variable's type is one of {"boolean": {}}, {"float": {"min": ..., "max": ..., "precision": ...}}, or (rarely) {"string": {"defaultValue": "..."}}. Float precision is an integer 0–3.
  • Each entry's values is keyed by variable UUID. The value is {"floatValue": <number>} or {"boolValue": <true|false>}.
  • Days with no recorded data have no entry in the dictionary — a missing date means "no data" for that day.
  • Saved searches and saved reports are application-shaped JSON objects with their own internal structure. Treat them as opaque if you're hand-editing — Correlate writes them, and rewrites them on every change.

JSON Schema (for tooling)

This Draft-07 schema covers the parts you're most likely to read or generate. Saved searches and saved reports are included as array so files validate, but their internal shape isn't strictly described here.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["variables", "entries"],
  "properties": {
    "schemaVersion": { "type": "integer", "minimum": 1 },
    "dataId":       { "type": "string", "format": "uuid" },
    "lastModified": { "type": "string", "format": "date-time" },
    "variables": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["id", "name", "sortOrder", "isDeleted", "type"],
        "properties": {
          "id":        { "type": "string", "format": "uuid" },
          "name":      { "type": "string", "maxLength": 32 },
          "note":      { "type": "string", "maxLength": 256 },
          "sortOrder": { "type": "integer", "minimum": 0 },
          "isDeleted": { "type": "boolean" },
          "type": {
            "type": "object",
            "oneOf": [
              {
                "required": ["boolean"],
                "properties": { "boolean": { "type": "object" } }
              },
              {
                "required": ["float"],
                "properties": {
                  "float": {
                    "type": "object",
                    "required": ["min", "max"],
                    "properties": {
                      "min":       { "type": "number" },
                      "max":       { "type": "number" },
                      "precision": { "type": "integer", "minimum": 0, "maximum": 3 }
                    }
                  }
                }
              }
            ]
          }
        }
      }
    },
    "entries": {
      "type": "object",
      "patternProperties": {
        "^[0-9]{4}-[0-9]{2}-[0-9]{2}$": {
          "type": "object",
          "required": ["values"],
          "properties": {
            "note":   { "type": "string", "maxLength": 512 },
            "values": {
              "type": "object",
              "patternProperties": {
                "^[0-9a-fA-F-]{36}$": {
                  "type": "object",
                  "oneOf": [
                    { "required": ["floatValue"], "properties": { "floatValue": { "type": "number"  } } },
                    { "required": ["boolValue"],  "properties": { "boolValue":  { "type": "boolean" } } }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "savedSearches": { "type": "array" },
    "savedReports":  { "type": "array" }
  }
}

Older files

Correlate reads files written by older versions of the app:

  • Files without schemaVersion are treated as schema 1 and migrated forward on load.
  • Files without lastModified are treated as just-modified.
  • Files without savedSearches or savedReports are treated as having empty lists.
  • Files without precision on a Number variable use the default (1 decimal).

Files with a schemaVersion newer than the running build are not read — the app refuses to clobber them. See Schema versioning.