API & MCP

Conversations API

A conversation is one interview between the AI and one respondent. The API returns who the respondent is, the AI summary with one answer per question, and the full transcript. For authentication, pagination and errors, see the API overview.

List conversations#

HTTP
GET /api/v1/projects/{project_id}/conversations

Returns a project's conversations, newest first, each with its AI summary. Transcripts are left out of the list. Fetch them with Get a conversation.

Query parameters#

ParameterDescription
statusOne or more of invited, opened, started, completed, cancelled, separated by commas. Without it, every status except invited is returned.
sentimentOne or more of positive, negative, neutral, mixed, separated by commas
created_afterOnly conversations created at or after this ISO 8601 time, such as 2026-05-01T00:00:00Z
created_beforeOnly conversations created at or before this time
searchText to look for in summaries, quotes and respondent details. Up to 200 characters.
limit1 to 100. Default 25.
cursorThe next_cursor of the previous page

Only completed conversations have a full summary, so most integrations send status=completed.

Example#

curl -G "https://diaform.io/api/v1/projects/b8acb3ab-1f3d-4a7e-a846-b7f493f86b6d/conversations" \
  -H "Authorization: Bearer $DIAFORM_API_KEY" \
  --data-urlencode "status=completed" \
  --data-urlencode "sentiment=negative,mixed" \
  --data-urlencode "created_after=2026-05-01T00:00:00Z" \
  --data-urlencode "limit=50"

Response#

JSON
{
  "data": [
    {
      "id": "0f8d43a2-6df9-49c8-bf5d-fd2b6ec2d9ee",
      "project_id": "b8acb3ab-1f3d-4a7e-a846-b7f493f86b6d",
      "status": "completed",
      "created_at": "2026-05-07T12:00:00.123456+00:00",
      "started_at": "2026-05-07T12:01:11.482913+00:00",
      "ended_at": "2026-05-07T12:15:41.204+00:00",
      "duration_seconds": 870,
      "country": "DE",
      "overall_sentiment": "mixed",
      "respondent": {
        "label": "alex@acme.com",
        "email": null,
        "identities": [
          { "type": "email", "value": "alex@acme.com", "source": "owner" },
          { "type": "name", "value": "Alex", "source": "ai" }
        ]
      },
      "metadata": {},
      "invite": {
        "id": "3a4f49c7-b8f4-4c44-8f74-fd8e4277c3e4",
        "status": "completed",
        "created_at": "2026-05-07T12:00:00.123456+00:00",
        "opened_at": "2026-05-07T12:01:11.482913+00:00",
        "completed_at": "2026-05-07T12:15:41.204+00:00"
      },
      "summary": {
        "overall_sentiment": "mixed",
        "answers": [
          {
            "question_id": "V1StGXR8_Z5jdHi6B-myT",
            "question": "How did your first week with the product go?",
            "summary": "Setup was quick, but inviting teammates was confusing.",
            "sentiment": "mixed",
            "confidence": "high",
            "quotes": ["I had no idea where the invite button was"]
          }
        ],
        "urgent_issues": [],
        "additional_insights": "Would pay more for a Slack integration."
      }
    }
  ],
  "has_more": true,
  "next_cursor": "WyIyMDI2LTA1LTA3VDEyOjAwOjAwLjEyMzQ1NiswMDowMCIsIjBmOGQ0M2EyIl0"
}

Conversation fields#

FieldTypeDescription
idstringConversation ID, the same one webhooks send as conversation_id
project_idstringThe project it belongs to
statusstringinvited, opened, started, completed or cancelled. The dashboard shows started as In progress.
created_atstringWhen the conversation was created. For invites, that's when the invite was created.
started_atstring or nullWhen the interview started
ended_atstring or nullWhen the conversation was completed or cancelled
duration_secondsnumber or nullTime from start to end
countrystring or nullThe respondent's country code, when known
overall_sentimentstring or nullpositive, negative, neutral or mixed. Same as summary.overall_sentiment.
respondent.labelstring or nullThe best name for the respondent: their email, then their name, then another identity
respondent.emailstring or nullLegacy field, null for new conversations. Read emails from respondent.identities.
respondent.identitiesarrayEverything known about the respondent. source is owner (you supplied it), ai (extracted from their messages) or system (added by Diaform).
metadataobjectEmpty for invites and direct links. For embedded conversations it holds embed details such as "embed": true and embed_parent_origin.
inviteobject or nullInvite details when the conversation came from a respondent invite, otherwise null
summaryobject or nullThe AI summary. null until the conversation ends and the summary is ready.

Summary fields#

FieldTypeDescription
overall_sentimentstringpositive, negative, neutral or mixed
answersarrayOne entry per question the respondent was asked
answers[].question_idstringThe question's ID in the project
answers[].questionstringThe question as it was asked
answers[].summarystringA short summary of the answer
answers[].sentimentstringpositive, negative, neutral or mixed
answers[].confidencestringhigh, medium or low: how fully the question was answered
answers[].quotesarrayNotable quotes in the respondent's own words. Often empty.
urgent_issuesarrayCritical problems the respondent raised, as short strings
additional_insightsstring or nullUseful feedback that didn't belong to any question

Get a conversation#

HTTP
GET /api/v1/conversations/{conversation_id}

Returns one conversation with every field of the list, plus the transcript in messages.

Example#

curl "https://diaform.io/api/v1/conversations/0f8d43a2-6df9-49c8-bf5d-fd2b6ec2d9ee" \
  -H "Authorization: Bearer $DIAFORM_API_KEY"

Response#

The fields shared with the list are shortened here.

JSON
{
  "id": "0f8d43a2-6df9-49c8-bf5d-fd2b6ec2d9ee",
  "project_id": "b8acb3ab-1f3d-4a7e-a846-b7f493f86b6d",
  "status": "completed",
  "overall_sentiment": "mixed",
  "summary": {},
  "messages": [
    {
      "role": "interviewer",
      "text": "Hi! Thanks for taking the time. How did your first week with the product go?"
    },
    {
      "role": "respondent",
      "text": "Setup was fast. But I had no idea where the invite button was."
    },
    {
      "role": "interviewer",
      "text": "Where did you expect to find it?"
    }
  ]
}
FieldTypeDescription
messagesarrayThe transcript in order. Empty when the respondent never replied.
messages[].rolestringinterviewer (the AI) or respondent
messages[].textstringWhat was said. Spoken answers appear as their transcription, and a choice or rating as text such as Selected answers: Pro.