> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developer.fortresstech.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.fortresstech.io/_mcp/server.

# List Conversations

GET https://api.fortresstech.io/v1/conversations

Available by RequestList conversations. A conversation is the running message thread between a property and one recipient;
every message belongs to exactly one.Look conversations up one of three ways, in this order of precedence:- **By recipient** — supply `recipientId` with a customer id or prospect id.
- **By household** — supply `householdId` together with `propertyId`. Returns the conversations for
  every member of the household.
- **By property** — supply `propertyId` alone, optionally narrowed with `status`.The recipient and household lookups embed the most recent inbound message under `lastReceivedMessage`.
The property lookup does not.This endpoint is part of our evolving API ecosystem.
To explore availability for your integration, please contact our team.Filtering, sorting, field selection, and pagination are not available on this endpoint. The `fields`, `sort`, `filter`, `page`, and `limit` query parameters are ignored.

Reference: https://developer.fortresstech.io/api-reference/messaging/list-conversations

## Authentication

- `x-api-key` header (required) — API Key authentication via header

## Request

### Query parameters

- `recipientId` (string, optional) — A customer id or prospect id. Takes precedence over the other lookups.
- `householdId` (string, optional) — Return conversations for every member of this household. Must be supplied together with `propertyId`.
- `propertyId` (string, optional) — Return conversations belonging to this property, or scope a `householdId` lookup.
- `status` (enum, optional) — Narrow a `propertyId` lookup to conversations in this state. Ignored by the other lookups.
  - Allowed values: `NEEDS_HELP`, `NEW`, `UNRESOLVED`, `RESOLVED`, `INVALID_PHONE_NUMBER`, `INVALID_EMAIL`

## Response

### 200

Expected response to a valid request. Returns an empty array when nothing matches.

- `list of Conversation`

## Errors

### 400 Bad Request Error

None of `recipientId`, `householdId` + `propertyId`, or `propertyId` was supplied.

- `type` (string, optional)
- `title` (string, optional)
- `status` (string, optional)
- `detail` (string, optional)
- `instance` (string, optional)

## Types

### Conversation

- `id` (string, optional) — Unique identifier for the conversation.
- `conversationStatus` (enum, optional) — Where the conversation stands. `NEEDS_HELP` prevails over every other value for as long as any message on the conversation has an open needs-help flag — see `needsHelpMessageIds` — and the conversation returns to whatever status the underlying workflow calls for once the last flag is resolved. `NEW` is set when an inbound message arrives and no one has responded yet, `UNRESOLVED` while a staff member is working it, and `RESOLVED` once it is closed. `INVALID_PHONE_NUMBER` and `INVALID_EMAIL` indicate the recipient could not be reached.
  - Allowed values: `NEEDS_HELP`, `NEW`, `UNRESOLVED`, `RESOLVED`, `INVALID_PHONE_NUMBER`, `INVALID_EMAIL`
- `messageType` (enum, optional) — The channel the conversation takes place on.
  - Allowed values: `SMS`, `EMAIL`
- `recipients` (list of ConversationRecipientsItems, optional) — Everyone linked to the conversation. A conversation may follow a person from prospect through customer, so both ids can appear over its lifetime.
- `recipient` (ConversationRecipient, optional) — The party currently being messaged.
- `emailSubject` (string, optional) — Subject line of the email thread. Email conversations only.
- `lastUsedEmailAddress` (string, optional) — Most recent email address used for this conversation. Email conversations only.
- `lastReceivedMessageId` (string, optional) — The most recent inbound message on the conversation.
- `needsHelpMessageIds` (list of string, optional) — Ids of messages on this conversation with an open needs-help flag. Empty when nothing is flagged. The conversation reads `NEEDS_HELP` for as long as this is non-empty.
- `propertyId` (string, optional)
- `createdAt` (datetime, optional)
- `updatedAt` (datetime, optional)
- `lastReceivedMessage` (messages_components-schemas-Base, optional) — The most recent inbound message, embedded in full. Only returned when the conversations are looked up by `recipientId` or by `householdId`; the `propertyId` lookup omits it. Attachment download URLs are not generated for the embedded message — read the message directly to get them.

### ConversationRecipientsItems

- `customerId` (string, optional)
- `prospectId` (string, optional)

### ConversationRecipient

The party currently being messaged.

- `customerId` (string, optional)
- `prospectId` (string, optional)
- `lastUsedPhoneNumberId` (string, optional) — The property phone number most recently used to reach this recipient.

### messages_components-schemas-Base

- `id` (string, optional) — Unique identifier for the message.
- `conversationId` (string, optional) — The conversation this message belongs to. Messages to the same recipient from the same property are grouped into a single conversation.
- `type` (enum, optional) — Direction and origin of the message. Messages created through `POST /messages` are always `OUTBOUND`.
  - Allowed values: `OUTBOUND`, `INBOUND`, `INTERNAL`, `EMAIL`, `UNRECOGNIZED_KEYWORD_RESPONSE`
- `content` (string, optional) — The body of the message. Limited to 1600 characters on send.
- `messageStatus` (string, optional) — Current delivery status. Statuses reported by the downstream carrier or email provider are passed through verbatim, so this is an open set rather than a fixed enum. Statuses set by Fortress: `CREATED`, `PROCESSING`, `FAILED`, `INVALID_PHONE_NUMBER`, `INVALID_EMAIL`, `RECEIVED`, `AUTOMATED`, `MASS_COMMUNICATION`. Statuses reported by the carrier: `QUEUED`, `SENT`, `DELIVERED`, `UNDELIVERED`, `FAILED`. The terminal statuses for SMS are `DELIVERED`, `UNDELIVERED`, and `FAILED`. For email they are `DELIVERED`, `FAILED`, and `REJECTED`.
- `messageStatusReason` (string, optional, nullable) — Explanation for the current status. Populated when a message fails to send.
- `messageSid` (string, optional) — Identifier assigned by the downstream SMS carrier. Absent until the message has been accepted for delivery.
- `customerStatus` (string, optional) — Status of the recipient at the time the message was created, as recorded in Fortress.
- `idempotencyId` (string, optional) — Caller-supplied key that uniquely identifies the send request. Reusing a key returns the original message rather than sending a duplicate.
- `isAutomated` (boolean, optional) — True when the message was generated by a Fortress automation rather than a person.
- `needsHelp` (boolean, optional, nullable) — True while this message has an open needs-help flag. Absent on messages that have never been flagged.
- `needsHelpDetails` (MessagesComponentsSchemasBaseNeedsHelpDetails, optional, nullable) — Who raised the needs-help flag, why, and who resolved it. Absent on messages that have never been flagged. The flag details survive resolution, so this still describes the original request after `needsHelp` returns to false.
- `subject` (string, optional) — Subject line. Email messages only.
- `emailAddress` (string, optional) — Recipient email address. Email messages only.
- `attachments` (list of MessagesComponentsSchemasBaseAttachmentsItems, optional) — Media attached to the message.
- `metadata` (map from string to any, optional) — Caller-supplied metadata, plus `sentAt` and `sentBy` recorded by Fortress at send time.
- `organizationId` (string, optional)
- `customerId` (string, optional) — Set when the recipient is a customer.
- `prospectId` (string, optional) — Set when the recipient is a prospect.
- `userId` (string, optional) — The Fortress user the message was sent on behalf of.
- `createdAt` (datetime, optional)
- `updatedAt` (datetime, optional)

### MessagesComponentsSchemasBaseNeedsHelpDetails

Who raised the needs-help flag, why, and who resolved it. Absent on messages that have never been flagged. The flag details survive resolution, so this still describes the original request after `needsHelp` returns to false.

- `reason` (string, optional, nullable) — Free-text reason supplied when the flag was raised.
- `flaggedByType` (enum, optional, nullable) — Who raised the flag: `agent` for Leslie, `user` for a Fortress staff member.
  - Allowed values: `agent`, `user`
- `flaggedById` (string, optional, nullable) — Identifies who raised the flag. `leslie` for the agent, otherwise a Fortress user id.
- `flaggedAt` (datetime, optional, nullable) — When the flag was raised.
- `resolvedByType` (enum, optional, nullable) — Who resolved the flag, using the same `agent`/`user` distinction as the flag itself.
  - Allowed values: `agent`, `user`
- `resolvedById` (string, optional, nullable) — Identifies who resolved the flag.
- `resolvedAt` (datetime, optional, nullable) — When the flag was resolved. Null while the flag is still open.

### MessagesComponentsSchemasBaseAttachmentsItems

- `key` (string, optional)
- `bucket` (string, optional)
- `type` (string, optional) — MIME type of the attachment.
- `url` (string, optional) — Time-limited download URL, generated per request. Expires 15 minutes after the response is issued.

## Examples

**Response**

```json
[
  {
    "id": "string",
    "conversationStatus": "NEEDS_HELP",
    "messageType": "SMS",
    "recipients": [
      {
        "customerId": "string",
        "prospectId": "string"
      }
    ],
    "recipient": {
      "customerId": "string",
      "prospectId": "string",
      "lastUsedPhoneNumberId": "string"
    },
    "emailSubject": "string",
    "lastUsedEmailAddress": "string",
    "lastReceivedMessageId": "string",
    "needsHelpMessageIds": [
      "string"
    ],
    "propertyId": "string",
    "createdAt": "2024-01-15T09:30:00Z",
    "updatedAt": "2024-01-15T09:30:00Z",
    "lastReceivedMessage": {
      "id": "string",
      "conversationId": "string",
      "type": "OUTBOUND",
      "content": "string",
      "messageStatus": "string",
      "messageStatusReason": "string",
      "messageSid": "string",
      "customerStatus": "string",
      "idempotencyId": "string",
      "isAutomated": true,
      "needsHelp": true,
      "needsHelpDetails": {
        "reason": "string",
        "flaggedByType": "agent",
        "flaggedById": "string",
        "flaggedAt": "2024-01-15T09:30:00Z",
        "resolvedByType": "agent",
        "resolvedById": "string",
        "resolvedAt": "2024-01-15T09:30:00Z"
      },
      "subject": "string",
      "emailAddress": "string",
      "attachments": [
        {
          "key": "string",
          "bucket": "string",
          "type": "string",
          "url": "string"
        }
      ],
      "metadata": {},
      "organizationId": "string",
      "customerId": "string",
      "prospectId": "string",
      "userId": "string",
      "createdAt": "2024-01-15T09:30:00Z",
      "updatedAt": "2024-01-15T09:30:00Z"
    }
  }
]
```

**SDK Code**

```python
import requests

url = "https://api.fortresstech.io/v1/conversations"

headers = {"x-api-key": "<apiKey>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.fortresstech.io/v1/conversations';
const options = {method: 'GET', headers: {'x-api-key': '<apiKey>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.fortresstech.io/v1/conversations"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("x-api-key", "<apiKey>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.fortresstech.io/v1/conversations")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<apiKey>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.fortresstech.io/v1/conversations")
  .header("x-api-key", "<apiKey>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.fortresstech.io/v1/conversations', [
  'headers' => [
    'x-api-key' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.fortresstech.io/v1/conversations");
var request = new RestRequest(Method.GET);
request.AddHeader("x-api-key", "<apiKey>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["x-api-key": "<apiKey>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.fortresstech.io/v1/conversations")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```