For developers and AI assistants

The Placemoir archive format

Version 1 · JSON Schema · Example

A Placemoir archive holds a whole Placemoir journal in one file: places, visits, ratings, notes, tags, weather, photos, voice memos and other attachments. Placemoir writes one when you export your journal (You › Export journal), and reads one back under You › Import an archive, or when you open the file from Files, Mail or AirDrop.

The format is public so that anyone, including scripts and AI assistants, can write files Placemoir imports: from Day One, Apple Journal, a spreadsheet, a travel blog or another app's export. This document is the whole contract. The machine-readable version is library-v1.json (JSON Schema 2020-12), and example-library.json is a complete example.

The words MUST, SHOULD and MAY are used as in RFC 2119.

For AI assistants and scripts

Someone has asked you to make a file they can import into Placemoir, an iPhone journal of places they've been and want to go. Follow these steps.

  1. Read what they gave you. It might be another app's export (Day One, Apple Journal, a spreadsheet), notes, or just a request like "the best coffee in Lisbon". If you can't tell which place, date or rating something belongs to, ask before guessing.
  2. Write library.json in the format below. It must validate against the schema; if you can run code, check it.
  3. Photos and audio. If the source has them and you can create files, put them in a media/ folder, list each on its visit as an attachment, and zip library.json and media/ together into a file ending in .placemoirarchive (see Writing archives from other apps). If you can't make a zip, hand over library.json alone, leave out attachments, and say the photos weren't included.
  4. Hand over the file as a download named after its contents, such as Lisbon 2025.placemoirarchive or Lisbon coffee.json. Tell the person: save it to the Files app, then open it (a .placemoirarchive) or choose it in Placemoir under You › Import an archive (either kind).

Rules:

  • Strict JSON. UTF-8, no comments, no trailing commas, no text before or after the object.
  • Don't invent anything. Only real places. Leave out any field you don't know instead of guessing: coordinates, addresses, ratings, dates. A place without coordinates still imports.
  • One place per real place. Put every visit to the same place under one place, not one place per visit.
  • Use stable ids. Give each place and visit an id, taken from the source when it has one (a Day One entry uuid, a spreadsheet row id). Then importing the same file again adds nothing new.
  • Keep their words. Copy the person's own text into notes as plain text. Turn Markdown or HTML into plain text, keep line breaks, and drop image placeholders.
  • Dates: keep the source's time and time zone offset when it has them. When there's only a day, write the day alone (2025-10-30).
  • Ratings: only when the source has one. Convert other scales to 1–5 in half steps (8/10 → 4, 3 of 4 → 4). Use goBack only when the person said whether they'd return.
  • Categories: pick the closest of restaurant, cafe, bar, hotel, park, museum, attraction, otherwise other. Bakeries and dessert shops are cafe; beaches, viewpoints and gardens are park; galleries are museum; shops, markets and anything else are attraction or other.
  • Want to go: a place they haven't been to yet (a recommendation, a trip plan) has no visits. It lands on their Want to go list. Put why it's on the list in the place's notes.
  • Recommendations you research: only places that exist and are open now, with a full street address. Leave out coordinates you aren't sure of.

If Placemoir refuses the file, it lists each problem with its location, like places[2].visits[0].rating: must be 1 to 5, not 9. Fix exactly those and hand over the file again.

At a glance

Lisbon.placemoirarchive          (a ZIP file)
├── library.json                 the journal, as JSON (required)
└── media/                       attachments named in library.json (optional)
    ├── 0D9E8F7A-…/Photo.jpg
    └── fado.m4a
{
  "format": "placemoir-library",
  "formatVersion": 1,
  "places": [
    {
      "name": "Tasca do Chico",
      "category": "bar",
      "latitude": 38.7115,
      "longitude": -9.1442,
      "visits": [
        {
          "date": "2025-10-30T22:15:00+01:00",
          "rating": 4.5,
          "goBack": "yes",
          "notes": "Fado after 10pm.",
          "attachments": [{ "path": "media/fado.m4a" }]
        }
      ]
    }
  ]
}

The file

  • Extension: .placemoirarchive. Uniform Type Identifier: com.tweetingbirds.placemoir.archive (conforms to public.data and public.archive). MIME type: application/vnd.placemoir.archive+zip.
  • The file MUST be a ZIP archive (PKWARE APPNOTE 6.3). Entries MUST be stored (method 0) or deflated (method 8), and MUST NOT be encrypted. ZIP64 is supported. Names SHOULD be UTF-8.
  • library.json MUST be at the top level. Placemoir also accepts it inside a single top-level folder (Lisbon/library.json), which is what Finder's Compress makes; then every path is relative to that folder. __MACOSX/ entries are ignored.
  • Placemoir writes library.json first, deflated, and then each attachment stored (photos and audio are already compressed) at media/<attachment id>/<file name>. Readers MUST NOT depend on that order or layout.
  • No attachment may be larger than 1 GB, and library.json no larger than 256 MB.

Without a zip

A library.json on its own (any file name ending in .json) also imports, from You › Import an archive. It can't carry attachments, so it MUST NOT list any. This is the easiest shape for a script or an AI assistant that can't make a zip.

library.json

UTF-8 JSON. Unknown keys are ignored at every level, so a file MAY carry extra data (for example the original app's ids) without harm. Every field below is optional unless marked required. null counts as missing.

Top level

Field Type
format string Required. Exactly "placemoir-library".
formatVersion integer Required. 1 for this document.
exportedAt date When the file was made. Shown before importing.
generator string What made the file, e.g. "Placemoir 1.0 (3) for iOS" or "Day One converter". Shown before importing.
places array of places

Place

Somewhere you've been or want to go. A place holds its visits.

Field Type
id id
name string Required, not blank.
category string restaurant, cafe, bar, hotel, park, museum, attraction or other. Placemoir ignores case, and imports any other value as other.
address string Street address.
locality string City or neighbourhood, as shown under the name ("Paris 11e").
country string
latitude, longitude number Decimal degrees, WGS 84. Give both or neither.
wantToGo boolean On the Want to go list. Defaults to true for a place with no visits and false otherwise.
notes string About the place itself, such as why you saved it. Notes about a visit go on the visit.
createdAt date When it was added to the journal.
visits array of visits

Visit

One time you went: its own date, rating, notes, weather and attachments.

Field Type
id id
date date Required. When you went, or checked in.
endDate date Check-out, for stays. Not before date.
rating number Stars, 1 to 5, in half steps. Other values in range round to the nearest half (4.3 → 4.5).
goBack string "Would you go back?": yes, maybe or no. Placemoir's Simple rating shows yes as "I'll be back" and no as "Never again".
notes string Plain text. Line breaks are kept.
tags array of strings Blank tags are dropped.
companions string Who you were with, as free text.
weather object summary (string, "Partly cloudy"), symbol (string, an SF Symbols name such as cloud.sun) and temperatureCelsius (number). All optional.
isDraft boolean An unfinished entry, shown with drafts. Default false.
createdAt, updatedAt date Default to date.
attachments array of attachments In the order they show.

Attachment

A photo, voice memo, PDF or other file. The bytes live in the archive; this record points at them.

Field Type
id id
path string Required. Where the file is in the archive, relative to library.json, with / between folders: media/lisbon/tasca.jpg. MUST NOT contain ... A leading ./ is allowed.
kind string photo, audio, pdf or file. When missing, it comes from the file extension.
filename string The name shown in the app. Defaults to the last part of path.
caption string
duration number Seconds, for audio.
createdAt date

Photos can be any format iOS reads (JPEG, HEIC, PNG). Placemoir keeps the original bytes and makes its own thumbnail. Audio SHOULD be M4A (AAC) or MP3. Video isn't supported yet; attach it as file if you want to keep it.

Dates

Dates are ISO 8601 strings. Placemoir writes 2026-11-01T18:30:00Z and reads any of these:

Written as Means
2026-11-01T18:30:00Z, 2026-11-01T18:30:00+01:00 That moment.
2026-11-01T18:30:00.250Z That moment, with fractions of a second.
2026-11-01T18:30:00, 2026-11-01T18:30 That time, in the time zone of the device importing it.
2026-11-01 Midday on that day, local time, so it never slips into the day before.

Anything else, such as Nov 1, 2026 or a Unix timestamp, is an error.

Ids

An id is any non-empty string, unique among the places (or visits, or attachments) in the file. Placemoir writes UUIDs. Any other string, such as a Day One entry id, is turned into a UUID the same way every time, so ids from another app keep working across imports.

Give every place and visit an id when you can. It is what makes importing the same file twice safe.

How Placemoir imports

Importing merges: it adds what's new and never changes or removes what's already in the journal.

  • A place is already there when it has the same id, or the same name (ignoring case) within 150 m. When either side has no position, the same name is enough. A matched place keeps its own fields, and gains any that were blank (address, locality, country, notes, position, a category other than other).
  • A visit is already there when it has the same id. A visit without an id is already there when the same place has a visit within a minute of it with the same notes. Visits already there are skipped, with their attachments.
  • An attachment keeps its id unless the journal already uses it, in which case it gets a new one.
  • A Want to go place that the file says you've visited ("wantToGo": false with visits) comes off the list.

So restoring a backup into the journal it came from adds nothing, and importing the same file twice adds nothing the second time. To replace a journal instead, use You › Delete all data first.

Before anything is imported, the whole file is checked. If anything is wrong, nothing is imported and Placemoir lists the problems with where to find them:

The library has 2 problems:
• places[0].visits[3].rating: must be 1 to 5, not 9.
• places[2].visits[0].attachments[0].path: “media/IMG_0042.jpg” isn’t in the archive.

Versions

formatVersion changes only when a file written to the new version would be misread by an app that reads the old one. Adding an optional field doesn't change it; readers ignore fields they don't know. Placemoir refuses a file with a formatVersion newer than it supports and asks you to update the app.

Version Placemoir Changes
1 1.0 First version.

Writing archives from other apps

The shortest path from another app is usually: export from that app, have a script or an AI assistant turn its export into library.json, then zip that with the photos.

# library.json and a media/ folder of photos it names, in the current folder:
zip -r -X "Day One.placemoirarchive" library.json media

Or in Python, which AI assistants that run code usually have:

import pathlib, zipfile
with zipfile.ZipFile("Day One.placemoirarchive", "w", zipfile.ZIP_DEFLATED) as archive:
    archive.write("library.json")
    for file in pathlib.Path("media").rglob("*"):
        if file.is_file():
            archive.write(file, file.as_posix())

Notes for common sources:

  • Day One (JSON export): each entry is a visit. Use location.placeName for the place name, location.latitude/longitude for its position, creationDate for date, text for notes, tags for tags, and the entry's uuid for the visit id. Photos are in the export's photos/ folder, named by their md5 and type. Group entries at the same place into one place with several visits.
  • Apple Journal (exported as HTML pages): each page is an entry. Its date and location become a visit and place, the text becomes notes, and the images in its Resources folder become photo attachments.
  • A list of places with no visits (a trip plan): places without visits. They land in Want to go.

Placemoir's own exports are the best reference for anything this page doesn't cover.