---
title: "Get analysis"
method: GET
path: "/v1/communities/{communityId}/projects/{projectId}/analysis"
tags: ["Analysis"]
---

# Get analysis

`GET /v1/communities/{communityId}/projects/{projectId}/analysis`

## Request

- Base URL: `https://api.subo.ai`
- URL: `https://api.subo.ai/v1/communities/{communityId}/projects/{projectId}/analysis`
- Auth: API key in header `X-API-Key`

Get current analysis: choice distributions, numeric stats, and AI summaries for open_text blocks.

## Path parameters

- `communityId` string, required
- `projectId` string, required

## Response `200`

Analysis result

- object
  - `data` Analysis
    - `project_id` string
    - `total_responses` integer: Individual answers recorded across all blocks, not respondents. A session that answered 6 blocks counts 6. This is the unit your plan's response limit counts.
    - `total_sessions` integer: Respondent sessions: the same number `GET /projects/{projectId}/responses` reports as `pagination.total`. Use this for "how many people answered".
    - `blocks` AnalysisBlock[]
      - `block_id` integer
      - `block_type` 'single_punch' | 'multi_punch' | 'open_text' | 'open_numeric' | 'rating' | 'opinion_scale' | 'nps' | 'ranking' | 'content_block'
      - `prompt` string
      - `position` integer
      - `response_count` integer
      - `distribution` AnalysisDistributionItem[], nullable: Answer distribution for `single_punch` and `multi_punch` blocks (one entry per chosen option, `option_id` set) and for the scale family (one entry per declared point, low to high, `option_id` null and `value` the point NUMBER — a point nobody picked is still listed with a count of 0). The glyph or Likert label a person would read lives on the block's `options` / `scale` in the script endpoint.
        - `option_id` integer, nullable
        - `value` string
        - `count` integer
        - `percentage` number, float
      - `stats` AnalysisStats: Descriptive statistics over the numeric answers. Returned for `open_numeric` and for the scale family (`rating` / `opinion_scale` / `nps`), whose answer is the picked point. `count` is the number of answers that parsed as a number, which can be lower than the block's `response_count`.
        - `count` integer
        - `mean` number, nullable
        - `min` number, nullable
        - `max` number, nullable
      - `ranking` AnalysisRankingItem[], nullable: Per-item results for `ranking` blocks, best first. Present instead of `distribution`, which cannot express an average rank.
        - `option_id` integer, nullable
        - `value` string: The item's text, as sent in `options`
        - `average_rank` number, float, nullable
        - `first_choice_count` integer: How many respondents ranked this item first
        - `ranked_count` integer: How many respondents ranked it at all
      - `summary` string, nullable: AI-generated summary text for open_text blocks
      - `summary_status` 'none' | 'processing' | 'done' | 'failed' | 'skipped': `none`: not requested yet; `processing`: AI job queued or running; `done`: summary available; `failed`: the AI call failed, `summary` is null, request it again; `skipped`: the community ran out of credits, `text_analysis.credits_short_by` says how many were missing
      - `text_analysis` object, nullable: `open_text` blocks only: whether this block's answers are sent for AI summary, and why. `state`: `on`, `off`, or `blocked` (most answers were personal data, so nothing was sent and no credits were spent). `source`: the setting that decided it: `block`, `personal_data_question` (the question asks for personal data, so it is off unless the block turns it on), `project`, `community`, or `personal_data_answers`. `personal_data`: what the question seems to ask for (`email`, `phone`, `name`, `address`, `birth_date`, `id_number`, `bank`, `handle`, `wallet`, `password`), kept even when the block was turned back on. `credits_short_by`: only when `summary_status` is `skipped`.
        - `state` 'on' | 'off' | 'blocked'
        - `source` 'block' | 'personal_data_question' | 'project' | 'community' | 'personal_data_answers'
        - `personal_data` string[]
        - `credits_short_by` integer

## Other responses

- `401`: Invalid or missing API key
- `403`: Forbidden
- `404`: Resource not found
- `429`: Rate limit exceeded — wait `retry_after` seconds before retrying. The same value appears in the `Retry-After` header.

---

[API](https://skmtc.dev/subo/apis/subo-api.md) · [All operations](https://skmtc.dev/subo/apis/subo-api/llms.txt) · [OpenAPI document](https://skmtc.dev/subo/apis/subo-api/revisions/12eab2ae4505?raw)
