Most/Docs

Location tracking

Most records where the participants of a conversation last were and who is sharing their location with the account, from what Messages.app writes: a position for every sent location and the start and stop of every location share. It answers through GET /v3/chats/{chat_id}/location, its history, three webhook events, the CLI, MCP and Most Desktop.

What Messages.app exposes, and what Most records#

A sent position — "Send My Current Location" in Messages — arrives as a `text/x-vlocation` card (`CL.loc.vcf`) whose Apple Maps link carries the coordinates. Most reads the card once, records one position for the sender's handle (latitude, longitude, the card's label and address when present, the map link, and the message time), and carries it on `message.received` as a `location` part instead of a media or contact part.

A location share — "Share My Location" — arrives as a start marker and, later, a stop marker (`item_type = 4` rows in chat.db). Most records the session: whose share it is (`inbound` when the counterparty shares with this account, `outbound` when this account shares with them), when it began, and when it ended. The moving points of a running share travel through Find My and are never written to chat.db, so Most does not claim to have them.

Both facts are persisted before anything is emitted, and persisted whether or not a webhook subscription matches, so the API answers for a conversation nobody subscribed to. Storage is idempotent on the Messages GUID of the row that produced the fact: a re-observed row records nothing and emits nothing.

A stop closes the newest still-open share for that chat, handle and direction whose start is not later than the stop. A delayed stop therefore cannot close a newer sharing session or produce an end before its start. Concurrent stop processing does not overwrite an already recorded end. The location API, CLI, MCP and desktop read the same persisted session.

Concurrent observations of the same stop GUID are serialized in PostgreSQL before checking its recorded end. That check and the eligible-share update commit together, so a duplicated stop cannot close another open share or emit another stopped event. A database or commit failure is not reported as a successful closure.

When no still-open session began by the stop time, the bridge logs the Messages row and GUID, handle, direction, stop time and chat id, and emits no stopped event. This observation does not prove that the start was never seen: it can also follow a later start or concurrent closure.

Read where a conversation's participants are#

`GET /v3/chats/{chat_id}/location` answers the newest recorded position per handle and the running shares; `?include_ended=true` adds the sessions that already ended. `GET /v3/chats/{chat_id}/location/history` answers every recorded position newest first, optionally for one `handle`, from `since` (RFC 3339). Omit `limit` for the complete matching history or supply a positive whole number to bound it. The value must fit the database's signed integer LIMIT; Most adds no default count or page cap. Both take the same service bearer as every other `/v3/chats` route.

GET /v3/chats/{chat_id}/location
{
  "chat_id": "2f1c6a8e-9d51-4c4a-8b0f-3a9c1d2e4f5a",
  "positions": [
    {"id": "7a3f0d2c-…", "handle": "+15550001111", "direction": "inbound",
     "latitude": 52.229676, "longitude": 21.012229,
     "label": "Current Location", "address": null,
     "map_url": "http://maps.apple.com/?ll=52.229676,21.012229",
     "observed_at": "2026-09-21T10:00:00+00:00",
     "source": "messages-app-current-location"}
  ],
  "shares": [
    {"id": "9b8c7d6e-…", "handle": "+15550001111", "direction": "inbound",
     "began_at": "2026-09-21T10:01:00+00:00", "ended_at": null}
  ]
}

Refusals#

  • An unknown chat answers 404 with `detail: "the requested resource does not exist"`, the same refusal every `/v3/chats/{chat_id}` route gives.
  • A supplied `limit` that is blank, nonpositive, fractional, nonnumeric or too large for the database LIMIT answers 400 with `detail: "limit must be a positive whole number representable by the database LIMIT"`.
  • `since` that is not RFC 3339 answers 400 with `detail: "since must be an RFC 3339 timestamp"`.
  • A conversation with no recorded position or share answers 200 with empty `positions` and `shares`; that is a fact about the conversation, not a failure.

Webhook events#

Subscribe to `location.received`, `location.sharing.started` and `location.sharing.stopped` exactly like the message events. Each delivery is signed the same way and carries `data.chat.id`, `data.handle.handle` and `data.direction`; `location.received` adds the coordinates, label, address, map link, `observed_at` and the `message_id` of the carrying message; the sharing events add `began_at` and, on stop, `ended_at`. `message.received` for a row carrying a sent location includes a `parts[]` entry of `type: "location"` with `latitude`, `longitude` and, when present, `label`, `address` and `map_url`.

location.received
{
  "id": "…", "type": "location.received", "created_at": "2026-09-21T10:00:00+00:00",
  "data": {
    "id": "7a3f0d2c-…", "chat": {"id": "2f1c6a8e-…"}, "handle": {"handle": "+15550001111"},
    "direction": "inbound", "message_id": "c4d5e6f7-…",
    "latitude": 52.229676, "longitude": 21.012229,
    "label": "Current Location", "address": null,
    "map_url": "http://maps.apple.com/?ll=52.229676,21.012229",
    "observed_at": "2026-09-21T10:00:00+00:00"
  }
}

CLI, MCP and desktop#

`most-cli location <chat_id> [--include-ended]` and `most-cli location-history <chat_id> [--handle <h>] [--since <rfc3339>] [--limit <n>]` perform the two reads and print the service's answer verbatim; a missing chat id is refused with `location requires a chat id` and exit status 2. The MCP tools `most_chat_location` and `most_chat_location_history` expose the same reads to an agent. Most Desktop's Location screen takes a chat id, shows the positions, the shares and the history, and opens a position's map link on click; a chat id that is not a UUID is refused before any request.

Read a conversation's location from the CLI
most-cli location 2f1c6a8e-9d51-4c4a-8b0f-3a9c1d2e4f5a
most-cli location 2f1c6a8e-9d51-4c4a-8b0f-3a9c1d2e4f5a --include-ended
most-cli location-history 2f1c6a8e-9d51-4c4a-8b0f-3a9c1d2e4f5a --handle +15550001111 --limit 50

Qualify real provider history#

Run node tests/location/provider-history.mjs against an isolated real Most service. It reads complete positions, active/ended shares and filtered history through the shipped CLI and checks meaningful refusals against independent provider evidence. Set MOST_BASE_URL, MOST_AGENT_API_TOKEN, MOST_TEST_CLI_BIN, MOST_TEST_SUCCESS_EXIT and MOST_TEST_LOCATION_ORACLE. The oracle contains chat_id, handle, since and full expected response objects current, all, history and filtered. Source revision, binary digest, commands, exit statuses and responses remain under .build/location/.

This qualifies reads of persisted real provider records, not generation or ingestion of new device events, webhook delivery or desktop rendering. Those require separate real-device and GUI journeys. There is no current make test-location target; a synthetic Messages database is not provider qualification.