# Find Decisions and Documents in iMessage History

Canonical: https://figment.so/blog/search-personal-imessage-history

iMessage threads hold a compressed record of real work: a link to the contract draft that became final, the "let's go with Option B" that settled a hire, the shared doc that turned into the product spec. Figment's `messages:read` scope exposes a search endpoint against the messages on a signed-in Mac, letting your app or agent retrieve those moments by keyword. The query worksheet below maps common retrieval tasks to the sync conditions they depend on.

## What iMessage history contains

[Apple's Messages in iCloud](https://support.apple.com/en-us/102545) keeps your message history synchronized across every device signed in to the same Apple Account, including your Mac. That history spans iMessage, SMS, MMS, and RCS conversations—not just blue-bubble threads. When Messages in iCloud is enabled on the iPhone, text-message forwarding is built in; a separate Text Message Forwarding switch is not required. The iPhone must be on, online, signed into the same Apple Account, and able to send and receive messages for new carrier messages to arrive.

Synced carrier-message history remains available on a paired Mac even when the iPhone is temporarily offline. The iPhone online requirement applies to new incoming and outgoing SMS, MMS, and RCS messages, not to reading already-synced history.

## Check the connection before you search

A newly connected Mac may still be syncing. Querying a non-ready service returns a partial window—or nothing. Check the per-service state first:

```
GET https://figment.so/api/apple-connect/v1/connections/{connection_id}
Authorization: Bearer ACCESS_TOKEN
```

A successful response includes per-service state:

```json
{
  "connection": {
    "id": "con_...",
    "mode": "live",
    "services": {
      "messages": {
        "state": "ready",
        "reason": null,
        "observedAt": 1731456000000
      }
    }
  }
}
```

Possible states: `connecting`, `needs_approval`, `syncing`, `ready`, `offline`, `reconnect_required`, `revoked`. Only proceed with search when `state` is `ready`. The endpoint enforces authorization; handle non-2xx responses. Use [your account page](/apple-connect/account) to monitor connection status and resolve setup issues.

A `ready` state means the service is authorized and available. It does not guarantee all historical messages have finished syncing—check `historyComplete` in search results for that.

## Query worksheet

This worksheet maps common retrieval tasks to query terms and sync requirements. Source for SMS/MMS/RCS scope: [Apple Messages in iCloud](https://support.apple.com/en-us/102545).

| Use case | Effective query terms | iPhone needed for new messages | Gap risk |
|---|---|---|---|
| Shared document links | `docs.google.com`, `notion.so`, `dropbox.com`, `figma.com` | Only for new SMS/RCS arrivals | Low for iMessage threads |
| Go/no-go decisions | `let's go`, `approved`, `confirmed`, `let's do it` | Only for new SMS/RCS arrivals | Medium—short replies lack standalone context |
| Contract or vendor references | Vendor name + `contract` or `agreement` | Only for new SMS/RCS arrivals | Low—proper nouns match precisely |
| Action-item assignments | `can you`, `please handle`, `by Friday`, `take care of` | Only for new SMS/RCS arrivals | Medium—forward-looking phrases are brief |
| File names and project codes | Exact file name, ticket ID, branch name | Only for new SMS/RCS arrivals | Low—exact string matches are reliable |
| Meeting coordination | `zoom`, `calendar invite`, `call at`, `reschedule` | Only for new SMS/RCS arrivals | Low—scheduling language is distinctive |
| Budget or pricing approvals | `approved the budget`, `go ahead`, dollar amounts | Only for new SMS/RCS arrivals | Medium—approval words are common and short |

**How to use this worksheet:** Start with the most specific term available—a URL hostname, a proper noun, or a dollar amount—rather than a generic word like "decision." Exact phrases reduce false matches. When a hit surfaces, use the `chatGuid` value from the result to fetch the surrounding thread.

## Searching with the API

The `messages:read` scope covers both message reads and search—no separate search permission exists.

```
GET https://figment.so/api/apple-connect/v1/connections/{connection_id}/messages/search
  ?query=TERM
  &chatGuid=CHAT_GUID   (optional — scope to one conversation)
  &limit=20             (default 20, max 100)
  &offset=0             (max 10000)
```

Build the URL with a URL constructor—never interpolate raw `chatGuid` values directly into a query string, as unencoded characters are misinterpreted by HTTP. If your grant was scoped to a specific conversation (a selected-chat grant), include that conversation's `chatGuid` to filter results.

A design illustration using curl:

```bash
BASE_URL="https://figment.so/api/apple-connect"
curl -G \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  --data-urlencode "query=contract draft" \
  --data-urlencode "limit=20" \
  "$BASE_URL/v1/connections/$CONNECTION_ID/messages/search"
```

Read credentials from environment variables. The developer app never receives the Apple password. Search scans bounded, locally available history—it is not a guaranteed full-text index of every message ever sent.

## Reading results and handling incomplete history

A search response has this shape:

```json
{
  "data": [
    {
      "guid": "...",
      "text": "...",
      "isFromMe": false,
      "chatGuid": "iMessage;...;..."
    }
  ],
  "mode": "live",
  "offset": 0,
  "nextOffset": 20,
  "hasMore": true,
  "historyComplete": false,
  "scope": "messages:read"
}
```

Key fields:

- **`chatGuid`** — use this value directly to fetch the full thread; do not construct the string manually, as the format varies by conversation type.
- **`hasMore` / `nextOffset`** — page forward by passing `nextOffset` as `offset` in the next request; stop when `hasMore` is `false` or `nextOffset` is `null`.
- **`historyComplete: false`** — sync is still in progress; results are a partial window of what will eventually be available.

To pull the thread around a match:

```
GET /v1/connections/{connection_id}/messages?chatGuid={chatGuid_from_result}&limit=20&offset=0
```

If a search returns nothing for a term you know was sent, check two things before concluding the message is gone:

1. **Connection state.** If `services.messages.state` is `syncing`, wait and retry—the message may not have arrived yet.
2. **Coverage.** If `historyComplete` is `false`, some older messages may not yet be on the Mac.

Empty results reflect locally available history at query time. They are not proof that a message was never sent.

---

iMessage history is an underused source of institutional memory. [Connect Apple Account](/apple-connect/developers) to give your app structured search access to that history.

**Related reading:**
- [OAuth for iCloud: Connect Apple Data to Your App](/oauth-for-icloud)
- [iMessage API for Search, Replies, and Agent Actions](/imessage-api)
- [Read and Search iMessages with Python](/blog/read-imessages-python)
- [Send an iMessage from Node.js Without Duplicates](/blog/send-imessage-nodejs)
