---
title: "Everything the dating detail screen needs, in one call"
method: GET
path: "/api/v1/contacts/{id}/dating"
---

# Everything the dating detail screen needs, in one call

`GET /api/v1/contacts/{id}/dating`

## Request

- Base URL: `https://memchats.com`
- URL: `https://memchats.com/api/v1/contacts/{id}/dating`
- Auth: HTTP bearer

The contact, the dating profile, the conversation state (whose turn, urgency and the sentence to show), the photos, the network history and the profile/chat discrepancies. Discrepancies are only computed when a screenshot is merged (POST /dating-profile) and are not stored, so this list is currently always empty.

## Path parameters

- `id` integer, required

## Response `200`

The aggregate

- object
  - `contact` object
    - `id` integer
    - `name` string
    - `conversationId` integer, nullable
  - `profile` DatingProfile, nullable
    - `network` string, nullable
    - `originNetwork` string, nullable
    - `nickname` string, nullable
    - `age` integer, nullable
    - `distanceKm` integer, nullable
    - `location` string, nullable
    - `residency` 'local' | 'visiting' | 'unknown'
    - `contentLanguage` string, nullable
    - `uiLanguage` string, nullable
    - `languages` string[]
    - `lookingFor` string, nullable: casual, serious, friendship or unclear.
    - `hasKids` boolean, nullable
    - `wantsKids` boolean, nullable
    - `ageRangeSought` object, nullable
      - `min` integer
      - `max` integer
    - `bio` string, nullable
    - `bioLanguage` string, nullable: ISO 639-1 of the bio: detected on the text, else contentLanguage.
    - `interests` string[]
    - `photoHooks` string[]
    - `updatedAt` string, date-time, nullable
  - `state` DatingConversationState
    - `whoseTurn` string, nullable: me, her or null.
    - `lastMessageFrom` string, nullable: me, her or null.
    - `sheAskedQuestion` boolean
    - `daysSinceLastMessage` integer, nullable
    - `urgency` 'owes_answer' | 'owes_reply' | 'waiting_on_her' | 'needs_new_reason' | 'fresh'
    - `urgencyMessage` string: Spanish sentence to show as is.
    - `herMedianReplyHours` number, nullable: null with fewer than two replies measured on times seen in the screenshots.
    - `herReplySamples` integer
    - `lastMessageAt` string, date-time, nullable
    - `lastMessageTimeKnown` boolean: false when the time was not visible in the imported screenshots: lastMessageAt is then the import time and daysSinceLastMessage is null.
    - `herLastMessageAt` string, date-time, nullable
    - `lastReplyDelayHours` number, nullable
    - `reactionSignal` string, nullable: faster_than_usual, normal, slower_than_usual or null.
    - `deferrals` integer
  - `photos` DatingPhoto[]
    - `id` integer
    - `position` integer, nullable
    - `hasFace` boolean, nullable
    - `caption` string, nullable
    - `width` integer, nullable
    - `height` integer, nullable
    - `source` 'auto' | 'manual': `manual` when the user cropped it by hand from a screenshot.
    - `screenshotId` integer, nullable: The original screenshot it came from (GET /contact-screenshots/{screenshotId}/image); null for photos saved before 2026-10-05.
    - `isCover` boolean: The cover the user chose: after a reorder, the first photo.
  - `networkHistory` DatingNetworkPeriod[]
    - `id` integer
    - `network` string
    - `startedAt` string, date
    - `endedAt` string, date, nullable
    - `note` string, nullable
  - `discrepancies` DatingDiscrepancy[]
    - `field` string
    - `profileValue` unknown
    - `chatValue` unknown
    - `message` string: Spanish sentence to show as is.
  - `suggestion` DatingSuggestion: The latest message proposal saved for this contact (the import wizard, or the last suggest-message). `null` when none was ever generated.
    - `text` string
    - `intent` 'open' | 'reply' | 'revive' | 'propose_date'
    - `charLimit` integer, nullable
    - `rationale` string, nullable
    - `language` string, nullable
    - `variants` object[], nullable: 2 or 3 drafts of distinct tone written in the same model call (2026-10-05), each within `charLimit`; the first one equals `text`. Absent or null when the model gave only one.
      - `text` string
      - `tone` 'direct' | 'playful' | 'curious'
    - `createdAt` string, date-time
  - `turn` DatingProposalTurn: Whose turn it is for the next proposal (2026-10-05). `write` with the intent to use (open without messages; reply, or propose_date when she put a live date on the table, after her message; revive after his own message 48 h or more ago). `wait`: his message is the last one and it is too soon to write again; `reviveAfter` says from when. Hours and `reviveAfter` are null when the screenshots showed no time.
    - `action` 'write' | 'wait'
    - `intent` 'open' | 'reply' | 'revive' | 'propose_date': Only with `write`.
    - `hoursSinceLastMessage` integer, nullable
    - `reviveAfter` string, date-time, nullable: Only with `wait`.
  - `recentMessages` DatingThreadMessage[]: The thread: the last 30 messages of either side, oldest first, with the language of each text. Older ones: GET /api/v1/contacts/{id}/dating/messages?before=<first id>.
    - `id` integer
    - `from` 'me' | 'her'
    - `text` string
    - `sentAt` string, date-time
    - `timeKnown` boolean: false: the time was not seen (screenshot without times, or typed without one) and sentAt only keeps the order.
    - `typedByHand` boolean: true: typed by hand without a time (show no time label). With timeKnown false and typedByHand false, the time was unreadable in the screenshots.
    - `language` string, nullable
  - `hasEarlierMessages` boolean: There are older messages than the first of `recentMessages`.

## Other responses

- `404`: Contact not found

---

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