Inkbox

> # Documentation index
> Fetch the complete documentation index at: https://inkbox.ai/sitemap.xml
> Use this file to discover all available pages before exploring further.

---

# Contact Memory and Correspondence
description: Read unified correspondence, generated memories, citations, and merge duplicate contacts

---


# Contact Memory and Correspondence

Inkbox can derive concise memories from a contact's email, SMS, iMessage, and call history. Every memory includes one or more citations to the source correspondence.

Contact list, create, update, and merge responses include `memory_count`, the number of active memories for that contact.

Fact text is organization-wide. For an identity-scoped caller, citations owned by that identity include their source ID, locator, and resolver URL; citations owned by other identities remain in the response but redact those source details. Organization-wide authenticated callers can inspect correspondence across the organization. Unavailable or inaccessible citations report only their source type and availability.

## List correspondence `GET`


Returns correspondence between one contact and one agent identity across supported channels.

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `identity_id` | UUID | Caller identity | Required for organization-wide callers; scoped callers use their own identity. |
| `channels` | string[] | All | Repeat or comma-separate `email`, `sms`, `imessage`, and `calls`. |
| `after` | datetime | None | Include items at or after this time. |
| `before` | datetime | None | Include items before this time. |
| `limit_per_channel` | integer | 25 | Default result limit for each selected channel. |
| `email_limit`, `sms_limit`, `imessage_limit`, `calls_limit` | integer | None | Override the limit for one channel. |
| `cursor` | string | None | Cursor returned by the previous response. |
| `order` | string | `desc` | `asc` or `desc`. |
| `content` | string | `preview` | `metadata`, `preview`, or `full`. |
| `transcripts` | string | `none` | `none`, `abridged`, or `full` for calls. |
| `include_failed` | boolean | `false` | Include failed correspondence. |

## List memories `GET`


Returns active memories in most-recently-updated order. Each fact contains `id`, `contact_id`, `content`, `confidence`, `origin`, timestamps, and a `citations` array.

## Get a memory `GET`


Returns one active memory with its citations under the same information-flow boundary described above.

## Delete a memory `DELETE`


Deletes one active memory. This requires an [admin-scoped API key](/docs/api-keys) or an authenticated Console user.

The response identifies the deleted fact and returns the contact's remaining memory state:

```json
{
  "deleted_fact_id": "FACT_ID",
  "memory_count": 2,
  "latest_memory": {
    "id": "LATEST_FACT_ID",
    "content": "Prefers morning meetings.",
    "updated_at": "2026-07-22T09:30:00Z"
  }
}
```

`latest_memory` is `null` when no active memories remain.

## Resolve a citation `GET`


Returns the source ID and locator after rechecking that the caller can still access the underlying correspondence. Returns `404` when the citation or its source is unavailable.

## Merge duplicate contacts `POST`


Merges the contacts in `losing_contact_ids` into the contact named in the path. The survivor retains the combined identifiers, correspondence, and memories; losing contacts become merged records. This operation requires an admin-scoped API key or authenticated Console user.

```json
{
  "losing_contact_ids": ["LOSING_CONTACT_ID"],
  "field_sources": {
    "preferred_name": "LOSING_CONTACT_ID",
    "company_name": "SURVIVING_CONTACT_ID"
  }
}
```

`field_sources` is optional. It selects which merged contact supplies each scalar profile field. Each value must be the survivor ID or one of the `losing_contact_ids`. Allowed keys are `preferred_name`, `name_prefix`, `given_name`, `middle_name`, `family_name`, `name_suffix`, `company_name`, `job_title`, `birthday`, and `notes`.

A contact can have at most 25 active memories. If the combined contacts would exceed that cap, the entire merge is rejected without changing any contact. Delete unwanted facts from the contacts being merged, then retry.

The response is the surviving contact and includes its current `memory_count` and `latest_memory`.
