# Conversation

URL: /business/nouns/conversation · Id: `noun:conversation`

> A Conversation is a Thread with one or more Contacts that a Worker must answer, such as a support request.

A Conversation is a [Thread](/business/nouns/thread) with one or more [Contacts](/business/nouns/contact) that a [Worker](/business/nouns/worker) must answer, such as a support request.

## Properties
| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `answeredAt` | `datetime` | No | When a Worker last answered. |
| `firstAnsweredAt` | `datetime` | No | When a Worker first answered; set once, never overwritten. `answeredAt` keeps the last answer. |
| `respondBy` | `datetime` | No | When the first answer is due: Setting `support.firstResponseWithin` per Offer, default 4 business hours. |
| `status` | `string` | No | Open, waiting on the Customer, or resolved; computed from its answers, closes and reopens. |
| `resolvedAt` | `datetime` | No | When it was resolved; empty again when the resolution reverses. |
| `resolution` | `string` | No | How it was resolved: the Customer said so, or 72 hours passed after an answer with no reply. |

<details>
<summary>Inherited from [Thread](/business/nouns/thread): 1 property</summary>

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `subject` | `string` | No | What the Thread is about. |

</details>

## Object
```json
{
  "$id": "https://api.sb/shiftnote.app/conversations/conversation_1",
  "$type": "Conversation",
  "subject": "Example subject",
  "answeredAt": "2026-10-22T12:00:00Z",
  "firstAnsweredAt": "2026-10-22T12:00:00Z",
  "respondBy": "2026-10-22T12:00:00Z",
  "status": "open",
  "resolvedAt": "2026-10-22T12:00:00Z",
  "resolution": "confirmed"
}
```

## Relationships
- <a id="rel-awaits"></a>A Conversation **awaits** one [Worker](/business/nouns/worker): one [Worker](/business/nouns/worker) owes each Conversation its next answer. `awaits`, inverse [`conversations`](/business/nouns/worker#rel-conversations).
- <a id="rel-customer"></a>A Conversation **has** one [Customer](/business/nouns/customer): the [Customer](/business/nouns/customer) a Conversation serves, so every answer reads that Customer’s records. `customer`, inverse [`opens`](/business/nouns/customer#rel-opens).
- <a id="rel-raises"></a>A Conversation **raises** many [Threads](/business/nouns/thread): the intake [Threads](/business/nouns/thread) a support Conversation opens, each deadline counted from the Conversation’s first [Message](/business/nouns/message). `raises`, inverse [`raisedIn`](/business/nouns/thread#rel-raised-in).
- <a id="rel-reports"></a>A Conversation **reports** one [Issue](/business/nouns/issue): the [Issue](/business/nouns/issue) or [Incident](/business/nouns/incident) a Conversation reports; resolving it answers every linked Conversation. `reports`, inverse [`conversations`](/business/nouns/issue#rel-conversations).

## Lifecycle

| State | Meaning | Moves to |
| --- | --- | --- |
| `open` (first) | A Contact wrote, and a Worker owes the answer by `respondBy`. | `waiting` on [`Conversation.answered`](/business/events/Conversation.answered); `waiting` on [`Action.asked`](/business/events/Action.asked) when the Question goes to this Conversation’s Contact; `resolved` on [`Conversation.closed`](/business/events/Conversation.closed) |
| `waiting` | A Worker answered, and the Customer owes the reply. | `open` on `Message.created` when a Contact’s Message arrives in this Conversation; `resolved` on [`Conversation.closed`](/business/events/Conversation.closed) |
| `resolved` | Resolved, confirmed by the Customer or assumed after 72 hours with no reply. | `open` on [`Conversation.reopened`](/business/events/Conversation.reopened) |

## Verbs
| Verb | Description | Subject | Event | Class |
| --- | --- | --- | --- | --- |
| [Conversation.answer](/business/nouns/conversation/answer) | Answer replies in a Conversation through the Channel it arrived on and closes the reply Task it opened. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.answered`](/business/events/Conversation.answered) | None. |
| [Conversation.assign](/business/nouns/conversation/assign) | Assign routes a Conversation to the Worker holding the right Role, by topic, Customer tier and language. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.assigned`](/business/events/Conversation.assigned) | Two-way: `try`, `send`, `do` |
| [Conversation.close](/business/nouns/conversation/close) | Close marks a Conversation resolved, confirmed by the Customer or assumed after 72 hours with no reply. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.closed`](/business/events/Conversation.closed) | Two-way: `try`, `send`, `do` |
| [Conversation.escalate](/business/nouns/conversation/escalate) | Escalate hands a Conversation and its summary to the Worker in the Role above, a Human only where one holds it. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.escalated`](/business/events/Conversation.escalated) | Two-way: `try`, `send`, `do` |
| [Conversation.reopen](/business/nouns/conversation/reopen) | Reopen reverses a Conversation’s resolution when a reversal signal arrives within 7 days, and grades the resolution a failure. | [Customer Lead](/agents/customer/customer-lead) | [`Conversation.reopened`](/business/events/Conversation.reopened) | Two-way: `try`, `send`, `do` |
| <a id="create"></a>[Conversation.create](/business/nouns/conversation/create) | Creates a Conversation. Inherited from [Noun](/business/nouns/noun). | None. | `Conversation.created` | Two-way: `try`, `send`, `do` |
| <a id="get"></a>[Conversation.get](/business/nouns/conversation/get) | Returns one Conversation by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` |
| <a id="list"></a>[Conversation.list](/business/nouns/conversation/list) | Returns Conversations, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` |
| <a id="update"></a>[Conversation.update](/business/nouns/conversation/update) | Changes the given properties of a Conversation. Inherited from [Noun](/business/nouns/noun). | None. | `Conversation.updated` | Two-way: `try`, `send`, `do` |
| <a id="delete"></a>[Conversation.delete](/business/nouns/conversation/delete) | Deletes a Conversation; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Conversation.deleted` | One-way: `send`, `do` |

## Permissions
Which Access level may call each Verb. One-way Verbs wait their delay window.

| Operation | `owner` | `admin` | `member` | `viewer` |
| --- | --- | --- | --- | --- |
| `Conversation.create` | Yes | Yes | Yes | No |
| `Conversation.get` | Yes | Yes | Yes | Yes |
| `Conversation.list` | Yes | Yes | Yes | Yes |
| `Conversation.update` | Yes | Yes | Yes | No |
| `Conversation.delete` | Yes | Yes | Yes | No |
| `Conversation.answer` | Yes | Yes | Yes | No |
| `Conversation.assign` | Yes | Yes | Yes | No |
| `Conversation.close` | Yes | Yes | Yes | No |
| `Conversation.escalate` | Yes | Yes | Yes | No |
| `Conversation.reopen` | Yes | Yes | Yes | No |

## Call it

**Ask**

```text
Answer the latest conversation.
```

**API**

```bash
curl -X POST https://api.sb/ledgerlark.com/conversations/conversation_1/answer \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"body":"Example body"}'
```

```json
{
  "api": "https://api.sb/ledgerlark.com",
  "conversation": {
    "$id": "https://api.sb/ledgerlark.com/conversations/conversation_1",
    "$type": "Conversation",
    "subject": "Example subject",
    "answeredAt": "2026-10-22T12:00:00Z"
  },
  "action": {
    "$id": "https://api.sb/ledgerlark.com/actions/action_1",
    "operation": "Conversation.answer",
    "status": "done"
  },
  "links": {
    "self": "https://api.sb/ledgerlark.com/actions/action_1"
  }
}
```

**SDK**

```ts
import { $ } from 'startup-builder'

const conversation = await $.Conversation.answer({ conversation: 'conversation_1', body: 'Example body' })
```

**CLI**

```bash
npx startup-builder do Conversation.answer --json '{"conversation":"conversation_1","body":"Example body"}'
```

**MCP**

```json
{
  "name": "do",
  "arguments": {
    "code": "return await $.Conversation.answer({ conversation: 'conversation_1', body: 'Example body' })"
  }
}
```

## Example
A [Customer](/business/nouns/customer) emails "my API key stopped working." The Conversation stays open until the support [Agent](/business/nouns/agent) answers and the Customer confirms the fix.