---
title: "Studies API reference"
canonical_url: https://zentrik.ai/docs/api/studies
markdown_url: https://zentrik.ai/docs/api/studies.md
last_reviewed: 2026-10-05
---

# Studies API reference

Read Study answers with participant details and submission times, maintain Study lifecycle and work context, and generate Findings.

- Human reference: https://zentrik.ai/docs/api/studies
- Complete Markdown index: https://zentrik.ai/docs/api/index.md
- Base URL: `https://zentrik.ai/api`
- Authentication: `Authorization: Bearer YOUR_API_KEY`
- Shared pagination and rate limits: https://zentrik.ai/docs/api/index.md#shared-conventions

## GET /external/v1/studies — List studies

Operation ID: `list-studies`

List Study metadata, format, Prototype stimulus, response counts, typed feedback configuration, accepted work context, and bounded draft-readiness counts. Use draftReadiness.hasBuilderContent instead of assuming that a draft with no responses or linked work is empty. Research answers, participant identity, prompts, and step content are excluded. Follow X-Has-More and advance offset by X-Limit to retrieve the complete catalog.

Required API key scopes: `studies:read`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `limit` | number | No | 1–100 results. Defaults to 20. |
| `offset` | number | No | Number of results to skip. |
| `status` | string | No | Exact Study status. |
| `moderationMode` | enum | No | Filter by self_guided, ai_moderated, or live_interview. |
| `initiativeId` | uuid | No | Current accepted Initiative context. |
| `ideaId` | uuid | No | Current accepted Idea context. |
| `updatedSince` | iso-date | No | Only Studies changed at or after this ISO-8601 timestamp, including new evidence, oldest change first. Use it to re-read evidence only for Studies that moved, and dedupe by id. |

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 200 | Success | Studies were retrieved. | Array<Study> |

### Example response

```json
[
  {
    "id": "study-uuid",
    "publicId": "STUDY-8",
    "workspaceId": "workspace-uuid",
    "name": "Scheduler direction check",
    "mainQuestion": "Can customers choose the right appointment type?",
    "status": "active",
    "type": "heatmap_interaction",
    "phase": "validation",
    "moderationMode": "live_interview",
    "studyFormat": "live_interview",
    "usesPrototype": true,
    "prototypeStimulus": {
      "prototypeId": "prototype-uuid",
      "prototypePublicId": "PROTOTYPE-7",
      "name": "Scheduling flow",
      "revisionId": "prototype-revision-uuid",
      "revisionNumber": 3,
      "status": "ready"
    },
    "responseCount": 7,
    "draftReadiness": {
      "hasBuilderContent": true,
      "stepCount": 2,
      "questionCount": 1,
      "interviewTopicCount": 4,
      "hasDecisionToInform": true,
      "hasLearningQuestion": true
    },
    "feedback": {
      "enabled": true,
      "prompt": "How clear was this interview?",
      "metric": "study_experience_clarity",
      "subject": {
        "type": "study",
        "id": "study-uuid"
      },
      "responseCount": 6,
      "averageRating": 4.17
    },
    "contexts": [
      {
        "linkId": "study-context-link-uuid",
        "entityType": "initiative",
        "entityId": "initiative-uuid",
        "publicId": "INITIATIVE-42",
        "label": "Unified scheduling",
        "productId": "product-uuid",
        "productName": "Denticon"
      }
    ],
    "initiativeIds": [
      "initiative-uuid"
    ],
    "ideaIds": [],
    "appPath": "/studies/STUDY-8",
    "createdAt": "2026-07-01T00:00:00Z",
    "updatedAt": "2026-07-14T10:00:00Z"
  }
]
```

---

## GET /external/v1/studies/:id — Get one study

Operation ID: `get-study`

Retrieve one Study by internal UUID or workspace-scoped public id. The response includes format, bounded draft readiness, accepted work context with link IDs, and participantUrl when a participant-facing Study link is available.

Required API key scopes: `studies:read`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid \| public id | Yes | For example STUDY-8. |

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 200 | Success | The Study was retrieved. | Study |

### Example response

```json
{
  "id": "study-uuid",
  "publicId": "STUDY-8",
  "workspaceId": "workspace-uuid",
  "name": "Scheduler direction check",
  "mainQuestion": "Can customers choose the right appointment type?",
  "status": "active",
  "type": "heatmap_interaction",
  "phase": "validation",
  "moderationMode": "self_guided",
  "studyFormat": "self_guided",
  "usesPrototype": true,
  "prototypeStimulus": {
    "prototypeId": "prototype-uuid",
    "prototypePublicId": "PROTOTYPE-7",
    "name": "Scheduling flow",
    "revisionId": "prototype-revision-uuid",
    "revisionNumber": 3,
    "status": "ready"
  },
  "responseCount": 7,
  "draftReadiness": {
    "hasBuilderContent": true,
    "stepCount": 2,
    "questionCount": 1,
    "interviewTopicCount": 4,
    "hasDecisionToInform": true,
    "hasLearningQuestion": true
  },
  "feedback": {
    "enabled": true,
    "prompt": "How clear was this study?",
    "metric": "study_experience_clarity",
    "subject": {
      "type": "study",
      "id": "study-uuid"
    },
    "responseCount": 6,
    "averageRating": 4.17
  },
  "contexts": [
    {
      "linkId": "study-context-link-uuid",
      "entityType": "initiative",
      "entityId": "initiative-uuid",
      "publicId": "INITIATIVE-42",
      "label": "Unified scheduling",
      "productId": "product-uuid",
      "productName": "Denticon"
    }
  ],
  "initiativeIds": [
    "initiative-uuid"
  ],
  "ideaIds": [],
  "appPath": "/studies/STUDY-8",
  "createdAt": "2026-07-01T00:00:00Z",
  "updatedAt": "2026-07-14T10:00:00Z",
  "participantUrl": "https://northstar.ideas.zentrik.ai/studies/scheduler-direction-check"
}
```

---

## GET /external/v1/studies/:id/responses — List study responses

Operation ID: `list-study-responses`

Read recorded Study answers, who provided them, and when each response was received. Responses are included even when the participant skipped the optional post-study rating. The MCP studies_get_responses tool returns the same items. Participant name, email, and organization (accountName) match the saved details shown in the Study Responses tab. Each item is a response; repeated submissions by one person remain separate. Use a Study UUID or public id such as STUDY-8. Results sort by submittedAt descending, then response id descending. Hold submittedTo fixed during a synchronization run, follow X-Has-More, and advance offset by X-Limit. Removed responses, planned interviews, unfinished conversations, and conversations with deleted sources are excluded.

Required API key scopes: `studies:read`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid \| public id | Yes | The Study reference, for example STUDY-8. |
| `submittedFrom` | ISO timestamp | No | Inclusive response submission time. |
| `submittedTo` | ISO timestamp | No | Exclusive response submission time. Must be after submittedFrom. |
| `limit` | number | No | 1–100 results. Defaults to 20. |
| `offset` | number | No | Number of results to skip. Defaults to 0. |

### Example request

```curl
curl 'https://zentrik.ai/api/external/v1/studies/STUDY-8/responses?limit=100' -H 'Authorization: Bearer YOUR_API_KEY'
```

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 200 | Success | Each item contains id, studyId, submittedAt, nullable participant and accountId, answers, nullable notes, a legacy click coordinate pair, and stepClicks. participant uses the same identity fields as the feedback feed and is null when unknown; snapshot-only identity can have a null id. submittedAt is the response timestamp, even when a Pulse rating arrived later. Answers preserve questionId, questionLabel, type, value, and available selectedOptionId, selectedOptions (id and label), rankedOptions (id, label, rank), cardAssignments (cardId, cardLabel, categoryId, categoryLabel), unplacedCards (cardId and cardLabel), followUpText, presentedOptionIds, rankingConfirmed, responseMode, and transcriptReviewed. Question and option labels are saved snapshots. Historical post-study ratings are omitted from answers; use the feedback endpoint for ratings. An empty answers array means no structured answers were saved. This endpoint does not export conversation transcripts or separate Prototype session recordings and analysis. Click coordinates only represent a response for studies that collect clicks. | Array<StudyResponse> |
| 400 | Invalid filters | Pagination or timestamps are invalid, or submittedFrom is not before submittedTo. | — |
| 404 | Not found | The Study does not exist in the API-key workspace. | — |

### Example response

```json
[
  {
    "id": "response-uuid",
    "studyId": "study-uuid",
    "submittedAt": "2026-09-15T10:00:00Z",
    "participant": {
      "id": null,
      "name": "Dana Ruiz",
      "email": "dana@example.com",
      "type": "public_user",
      "accountId": "account-uuid",
      "accountName": "Northstar Dental",
      "account": {
        "id": "account-uuid",
        "name": "Northstar Dental"
      }
    },
    "accountId": "account-uuid",
    "answers": [
      {
        "questionId": "question-1",
        "questionLabel": "What would make scheduling easier?",
        "type": "text",
        "value": "Keep the appointment list visible.",
        "followUpText": "I lose my place when switching views."
      }
    ],
    "notes": null,
    "click": {
      "x": 0.25,
      "y": 0.6
    },
    "stepClicks": [
      {
        "stepId": "step-1",
        "stepLabel": "Choose an appointment",
        "x": 0.25,
        "y": 0.6,
        "feedback": "I expected the list here."
      }
    ]
  }
]
```

---

## PATCH /external/v1/studies/:id — Update a study

Operation ID: `update-study`

Update the Study fields needed for catalog curation and lifecycle management. Omitted fields stay unchanged. Study format remains fixed, and the normal publish-readiness and lifecycle-transition rules still apply. researchBrief is a complete replacement when supplied.

Required API key scopes: `studies:write`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid \| public id | Yes | For example STUDY-8. |

### JSON request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | No | Clear Study name, up to 160 characters. |
| `mainQuestion` | string | No | Primary learning question. |
| `status` | enum | No | draft, active, closed, or archived. Invalid transitions are rejected. |
| `phase` | enum | No | discovery, definition, or validation. |
| `allowPublicAccess` | boolean | No | Whether the participant URL can be opened without sign-in. |
| `researchBrief` | object | No | Complete audience, decisionToInform, learningQuestion, and optional sufficiencyCriteria brief. |

### Example request

```curl
curl -X PATCH https://zentrik.ai/api/external/v1/studies/STUDY-8 \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Can customers choose the right appointment type?","phase":"validation"}'
```

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 200 | Success | The stored Study was returned after the update. | Study |
| 400 | Invalid request | The body, field values, publish readiness, or lifecycle transition is invalid. | — |
| 404 | Not found | The Study does not exist in the API-key workspace. | — |

### Example response

```json
{
  "id": "study-uuid",
  "publicId": "STUDY-8",
  "workspaceId": "workspace-uuid",
  "name": "Scheduler direction check",
  "mainQuestion": "Can customers choose the right appointment type?",
  "status": "active",
  "type": "heatmap_interaction",
  "phase": "validation",
  "moderationMode": "self_guided",
  "studyFormat": "self_guided",
  "usesPrototype": true,
  "prototypeStimulus": {
    "prototypeId": "prototype-uuid",
    "prototypePublicId": "PROTOTYPE-7",
    "name": "Scheduling flow",
    "revisionId": "prototype-revision-uuid",
    "revisionNumber": 3,
    "status": "ready"
  },
  "responseCount": 7,
  "draftReadiness": {
    "hasBuilderContent": true,
    "stepCount": 2,
    "questionCount": 1,
    "interviewTopicCount": 4,
    "hasDecisionToInform": true,
    "hasLearningQuestion": true
  },
  "feedback": {
    "enabled": true,
    "prompt": "How clear was this study?",
    "metric": "study_experience_clarity",
    "subject": {
      "type": "study",
      "id": "study-uuid"
    },
    "responseCount": 6,
    "averageRating": 4.17
  },
  "contexts": [
    {
      "linkId": "study-context-link-uuid",
      "entityType": "initiative",
      "entityId": "initiative-uuid",
      "publicId": "INITIATIVE-42",
      "label": "Unified scheduling",
      "productId": "product-uuid",
      "productName": "Denticon"
    }
  ],
  "initiativeIds": [
    "initiative-uuid"
  ],
  "ideaIds": [],
  "appPath": "/studies/STUDY-8",
  "createdAt": "2026-07-01T00:00:00Z",
  "updatedAt": "2026-07-14T10:00:00Z",
  "participantUrl": "https://northstar.ideas.zentrik.ai/studies/scheduler-direction-check"
}
```

---

## POST /external/v1/studies/:id/contexts — Link study work

Operation ID: `link-study-context`

Attach one existing work record to the Study. The entity must belong to the API-key workspace. Repeating an existing link is idempotent.

Required API key scopes: `studies:write`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid \| public id | Yes | For example STUDY-8. |

### JSON request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `entityType` | enum | Yes | idea, initiative, opportunity, or feature. |
| `entityId` | uuid | Yes | Internal UUID returned by the matching list endpoint. |

### Example request

```curl
curl -X POST https://zentrik.ai/api/external/v1/studies/STUDY-8/contexts \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"entityType":"initiative","entityId":"initiative-uuid"}'
```

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 200 | Success | The updated Study and accepted context were returned. | Study |
| 404 | Not found | The Study or target does not exist in the API-key workspace. | — |

### Example response

```json
{
  "id": "study-uuid",
  "publicId": "STUDY-8",
  "workspaceId": "workspace-uuid",
  "name": "Scheduler direction check",
  "mainQuestion": "Can customers choose the right appointment type?",
  "status": "active",
  "type": "heatmap_interaction",
  "phase": "validation",
  "moderationMode": "self_guided",
  "studyFormat": "self_guided",
  "usesPrototype": true,
  "prototypeStimulus": {
    "prototypeId": "prototype-uuid",
    "prototypePublicId": "PROTOTYPE-7",
    "name": "Scheduling flow",
    "revisionId": "prototype-revision-uuid",
    "revisionNumber": 3,
    "status": "ready"
  },
  "responseCount": 7,
  "draftReadiness": {
    "hasBuilderContent": true,
    "stepCount": 2,
    "questionCount": 1,
    "interviewTopicCount": 4,
    "hasDecisionToInform": true,
    "hasLearningQuestion": true
  },
  "feedback": {
    "enabled": true,
    "prompt": "How clear was this study?",
    "metric": "study_experience_clarity",
    "subject": {
      "type": "study",
      "id": "study-uuid"
    },
    "responseCount": 6,
    "averageRating": 4.17
  },
  "contexts": [
    {
      "linkId": "study-context-link-uuid",
      "entityType": "initiative",
      "entityId": "initiative-uuid",
      "publicId": "INITIATIVE-42",
      "label": "Unified scheduling",
      "productId": "product-uuid",
      "productName": "Denticon"
    }
  ],
  "initiativeIds": [
    "initiative-uuid"
  ],
  "ideaIds": [],
  "appPath": "/studies/STUDY-8",
  "createdAt": "2026-07-01T00:00:00Z",
  "updatedAt": "2026-07-14T10:00:00Z",
  "participantUrl": "https://northstar.ideas.zentrik.ai/studies/scheduler-direction-check"
}
```

---

## DELETE /external/v1/studies/:id/contexts/:linkId — Unlink study work

Operation ID: `unlink-study-context`

Detach accepted work context by the linkId returned on the Study. Zentrik keeps rejection memory and refuses to remove the only accepted product context.

Required API key scopes: `studies:write`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid \| public id | Yes | For example STUDY-8. |
| `linkId` | uuid | Yes | Context link ID returned in Study.contexts. |

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 200 | Success | The updated Study context was returned. | Study |
| 400 | Last context | Attach replacement product context before removing the final accepted link. | — |
| 404 | Not found | The Study or link does not exist in the API-key workspace. | — |

### Example response

```json
{
  "id": "study-uuid",
  "publicId": "STUDY-8",
  "workspaceId": "workspace-uuid",
  "name": "Scheduler direction check",
  "mainQuestion": "Can customers choose the right appointment type?",
  "status": "active",
  "type": "heatmap_interaction",
  "phase": "validation",
  "moderationMode": "self_guided",
  "studyFormat": "self_guided",
  "usesPrototype": true,
  "prototypeStimulus": {
    "prototypeId": "prototype-uuid",
    "prototypePublicId": "PROTOTYPE-7",
    "name": "Scheduling flow",
    "revisionId": "prototype-revision-uuid",
    "revisionNumber": 3,
    "status": "ready"
  },
  "responseCount": 7,
  "draftReadiness": {
    "hasBuilderContent": true,
    "stepCount": 2,
    "questionCount": 1,
    "interviewTopicCount": 4,
    "hasDecisionToInform": true,
    "hasLearningQuestion": true
  },
  "feedback": {
    "enabled": true,
    "prompt": "How clear was this study?",
    "metric": "study_experience_clarity",
    "subject": {
      "type": "study",
      "id": "study-uuid"
    },
    "responseCount": 6,
    "averageRating": 4.17
  },
  "contexts": [
    {
      "linkId": "study-context-link-uuid",
      "entityType": "initiative",
      "entityId": "initiative-uuid",
      "publicId": "INITIATIVE-42",
      "label": "Unified scheduling",
      "productId": "product-uuid",
      "productName": "Denticon"
    }
  ],
  "initiativeIds": [
    "initiative-uuid"
  ],
  "ideaIds": [],
  "appPath": "/studies/STUDY-8",
  "createdAt": "2026-07-01T00:00:00Z",
  "updatedAt": "2026-07-14T10:00:00Z",
  "participantUrl": "https://northstar.ideas.zentrik.ai/studies/scheduler-direction-check"
}
```

---

## GET /external/v1/studies/:id/evidence — Get study findings

Operation ID: `get-study-evidence`

Retrieve the active draft Findings version and its freshness for one Study. Findings include the decision summary, readiness, finding statements, evidence strength, sample count, review status, evidence-reference counts, recommended follow-ups, and open questions. This privacy-bounded endpoint never returns participant identity, raw responses, notes, transcripts, or verbatim evidence excerpts.

Required API key scopes: `studies:read`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid \| public id | Yes | For example STUDY-8. |

### Example request

```curl
curl -X GET https://zentrik.ai/api/external/v1/studies/STUDY-8/evidence \
  -H 'Authorization: Bearer YOUR_API_KEY'
```

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 200 | Success | The active Findings and freshness were retrieved. findings is null when no version exists. | StudyEvidence |
| 404 | Not found | The Study does not exist in the API-key workspace. | — |

### Example response

```json
{
  "id": "study-uuid",
  "publicId": "STUDY-8",
  "name": "Scheduler direction check",
  "findings": {
    "versionId": "findings-version-uuid",
    "versionNumber": 2,
    "generatedAt": "2026-07-14T09:00:00Z",
    "decisionSummary": {
      "conclusion": "Customers need clearer appointment-type choices.",
      "evidenceStrength": "moderate",
      "productImplication": "Clarify labels before expanding the scheduling flow."
    },
    "readiness": {
      "status": "gathering_evidence",
      "note": "Interview one more office manager."
    },
    "findings": [
      {
        "id": "finding-uuid",
        "kind": "finding",
        "statement": "Participants missed the appointment-type control.",
        "evidenceStrength": "moderate",
        "sampleCount": 3,
        "reviewStatus": "draft",
        "evidenceReferenceCount": 4
      }
    ],
    "recommendedFollowUps": [
      "Test clearer appointment-type labels."
    ],
    "openQuestions": [
      "Does the result vary by office role?"
    ]
  },
  "findingsFreshness": {
    "hasFindings": true,
    "stale": false,
    "evidenceUpdatedAt": "2026-07-14T08:30:00Z",
    "findingsGeneratedAt": "2026-07-14T09:00:00Z"
  },
  "privacy": {
    "participantIdentityIncluded": false,
    "rawResponsesIncluded": false,
    "evidenceExcerptsIncluded": false
  }
}
```

---

## POST /external/v1/studies/:id/findings/generate — Generate study findings

Operation ID: `generate-study-findings`

Run Zentrik’s evidence-grounded AI synthesis for a Study and store a draft Findings version. The operation requires submitted responses. When the active Findings already cover the latest evidence, the request is an idempotent no-op and returns changed: false. The returned item follows the same privacy boundary as the Study evidence endpoint and still requires human review in Zentrik.

Required API key scopes: `studies:write`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid \| public id | Yes | For example STUDY-8. |

### Example request

```curl
curl -X POST https://zentrik.ai/api/external/v1/studies/STUDY-8/findings/generate \
  -H 'Authorization: Bearer YOUR_API_KEY'
```

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 200 | Success | Findings were generated, or current Findings were returned with changed set to false. | StudyFindingsGenerationResult |
| 400 | No responses | The Study has no submitted responses to synthesize. | — |
| 404 | Not found | The Study does not exist in the API-key workspace. | — |

### Example response

```json
{
  "operation": "study_findings_generation",
  "changed": true,
  "item": {
    "id": "study-uuid",
    "publicId": "STUDY-8",
    "name": "Scheduler direction check",
    "findings": {
      "versionId": "findings-version-uuid",
      "versionNumber": 2,
      "generatedAt": "2026-07-14T09:00:00Z",
      "decisionSummary": {
        "conclusion": "Customers need clearer appointment-type choices.",
        "evidenceStrength": "moderate",
        "productImplication": "Clarify labels before expanding the scheduling flow."
      },
      "readiness": {
        "status": "gathering_evidence",
        "note": "Interview one more office manager."
      },
      "findings": [
        {
          "id": "finding-uuid",
          "kind": "finding",
          "statement": "Participants missed the appointment-type control.",
          "evidenceStrength": "moderate",
          "sampleCount": 3,
          "reviewStatus": "draft",
          "evidenceReferenceCount": 4
        }
      ],
      "recommendedFollowUps": [
        "Test clearer appointment-type labels."
      ],
      "openQuestions": [
        "Does the result vary by office role?"
      ]
    },
    "findingsFreshness": {
      "hasFindings": true,
      "stale": false,
      "evidenceUpdatedAt": "2026-07-14T08:30:00Z",
      "findingsGeneratedAt": "2026-07-14T09:00:00Z"
    },
    "privacy": {
      "participantIdentityIncluded": false,
      "rawResponsesIncluded": false,
      "evidenceExcerptsIncluded": false
    }
  }
}
```
