---
title: "Google Lsa Conversations"
method: GET
path: "/admin/lsa/conversations"
tags: ["admin", "lsa-admin"]
---

# Google Lsa Conversations

`GET /admin/lsa/conversations`

## Request

- Base URL: `https://api-docs.upsmith.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api-docs.upsmith.com/admin/lsa/conversations`
- Auth: one of:
  - API key in header `x-api-key`
  - HTTP bearer

Read ``local_services_lead_conversation`` straight from Google for one LSA account
(optionally scoped to one ``lead_resource_name``) and, when ``reconcile`` is set, diff the
consumer messages against ``leads.google_lsa_conversation_message``.

The ground-truth read behind the "does Google return the customer's later replies?"
question. ``missing_from_db_count`` is the dropped set — messages Google returned that we
never stored. ``missing_from_thread_count`` is reported separately and is usually benign
(lead intakes and revival openers are persisted as synthetic intakes, so they carry no
conversation-keyed external_id); PHONE_CALL/BOOKING rows land in ``non_message_count``
rather than looking like loss. No watermark/lookback suppression (unlike the poller);
``message_channel_only=false`` widens past the MESSAGE channel. Read-only; one Google Ads op.

## Query parameters

- `organization_id` string, required
- `google_customer_id` string, required
- `lead_resource_name` string, nullable
- `lookback_days` integer
- `message_channel_only` boolean
- `reconcile` boolean

## Headers

- `organization-id` string, nullable
- `timezone` string
- `x-user-id` string, nullable
- `x-actor-email` string, nullable
- `x-request-source` string, nullable
- `x-operation-id` string, nullable
- `x-commit-message` string, nullable
- `x-confirmation-id` string, nullable
- `x-chat-id` string, nullable

## Response `200`

Successful Response

- GoogleLsaConversationsProbe: Ground-truth read of an LSA account's conversation messages straight from Google — the read that tells "Google never returned the reply" apart from "we dropped it". Ingest is reconciled against leads.google_lsa_conversation_message, the durable log the poller writes for every message it fetches. Thread presence is reported separately (``missing_from_thread_count``) because it is legitimately path-dependent and a miss there does not mean the message was lost.
  - `organization_id` string, required
  - `google_customer_id` string, required
  - `lead_resource_name` string, nullable: When set, results are scoped to this one Google LSA lead resource name.
  - `since` string, date-time, required: Lower bound (UTC) on event_date_time that was queried.
  - `lookback_days` integer, required
  - `message_channel_only` boolean, required: Whether the query was restricted to the MESSAGE channel (the poller's filter). False = every channel.
  - `reconciled` boolean, required: Whether consumer messages were diffed against what we stored.
  - `google_count` integer, required: Conversation messages Google's API returned.
  - `consumer_count` integer, required: Of those, how many are CONSUMER (customer) rows, messages or not.
  - `consumer_message_count` integer, required: Of the consumer rows, how many are actual messages (text or attachments) — the ingest denominator.
  - `non_message_count` integer, required: Consumer rows that carry no message: PHONE_CALL and BOOKING events on the lead. Excluded from the ingest counts because they can never be an interaction.
  - `present_in_db_count` integer, nullable: Consumer messages we ingested (present in leads.google_lsa_conversation_message). None if skipped.
  - `missing_from_db_count` integer, nullable: Consumer messages Google returned that we never stored — the genuinely dropped set, and the only count here that means message loss. None if reconcile skipped.
  - `missing_from_thread_count` integer, nullable: Ingested consumer messages with no conversation-id-keyed interaction. Expected and benign for lead intakes and revival openers (both persisted as synthetic intakes); investigate only alongside a customer reporting an unanswered reply. None if reconcile skipped.
  - `messages` GoogleLsaProbedConversationMessage[]
    - `conversation_id` string, required: Google's per-message conversation event id.
    - `lead_resource_name` string, nullable
    - `participant_type` string, nullable: "CONSUMER" (customer) or "ADVERTISER" (our/business sends).
    - `conversation_channel` string, nullable
    - `event_date_time` string, date-time, required
    - `text` string, nullable
    - `is_message` boolean, required: Whether this row is an actual message (has text or attachments). False for PHONE_CALL / BOOKING rows, which are events on the lead, never something that could land in a thread.
    - `in_db` boolean, nullable: When reconciled: did we ingest this message? True = present in leads.google_lsa_conversation_message, the durable log the poller writes for every message it fetched. False here is the real 'we dropped it'. None if reconcile skipped.
    - `emitted` boolean, nullable: When reconciled: did the poller emit a bus event for this message (emitted_event_id set)? Always false for PHONE_CALL rows and our own ADS_API sends, which are persistence-only. Also false on rows written by the historical backfill, which recorded no event id — read it as authoritative only for recently polled messages.
    - `in_thread` boolean, nullable: When reconciled: is there an engagement.event_interaction keyed to this message (conversation_id, or adv:conversation_id for a CSR takeover)? False is NOT loss on its own — a lead's originating message and a revival's opener are both persisted as synthetic intakes with no external_id.

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/upsmith/apis/upsmith-api.md) - [All operations](https://skmtc.dev/upsmith/apis/upsmith-api/llms.txt) - [OpenAPI document](https://skmtc.dev/upsmith/apis/upsmith-api/revisions/cce8b07a5787?raw)
