---
title: "List Clusters"
method: POST
path: "/v1/clusters/list"
tags: ["Clusters"]
---

# List Clusters

`POST /v1/clusters/list`

This endpoint allows you to list clusters.

## Query parameters

- `limit` integer, nullable
- `page_size` integer, nullable
- `offset` integer, nullable
- `page` integer, nullable
- `cursor` string, nullable
- `next_cursor` string, nullable
- `after` string, nullable
- `include_total` boolean

## Request body

- ListClustersRequest — Request model for listing clusters. Inherits body-level limit/page_size/offset/page (BACKE-2846) — body values win over query pagination via merge_body_pagination.
  - `limit` integer, nullable — Page size. A body value wins over the `limit` query param.
  - `page_size` integer, nullable — Alias for `limit` (page size). If both are given, `limit` wins.
  - `offset` integer, nullable — Number of results to skip (legacy, use cursor instead). A body value wins over the `offset` query param.
  - `page` integer, nullable — 1-indexed page number. Folds to offset = (page-1) * limit. If both `page` and `offset` are given, `offset` wins.
  - `filters` LogicalOperatorInput — Represents a logical operation (AND, OR, NOT) on filter conditions. Allows nesting with a defined depth limit. Also supports shorthand syntax where field names can be passed directly as key-value pairs for equality filtering (e.g., {"metadata.title": "value"}).
    - `AND` union[], nullable — Logical AND operation - all conditions must be true
      - union
        - LogicalOperatorInput — recursive
        - FilterCondition — Represents a single filter condition. Attributes: field: The field to filter on operator: The comparison operator value: The value to compare against
          - `field` string, required — Field name to filter on
          - `operator` 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'nin' | 'contains' | 'starts_with' | 'ends_with' | 'regex' | 'exists' | 'is_null' | 'text' | 'phrase' | 'geo_radius' | 'geo_bounding_box' | 'geo_polygon' — Supported filter operators across database implementations.
          - `value` union, required — Value to compare against
            - DynamicValue — A value that should be dynamically resolved from the query request.
              - …
            - unknown
    - `OR` union[], nullable — Logical OR operation - at least one condition must be true
      - union
        - LogicalOperatorInput — recursive
        - FilterCondition — Represents a single filter condition. Attributes: field: The field to filter on operator: The comparison operator value: The value to compare against
          - `field` string, required — Field name to filter on
          - `operator` 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'nin' | 'contains' | 'starts_with' | 'ends_with' | 'regex' | 'exists' | 'is_null' | 'text' | 'phrase' | 'geo_radius' | 'geo_bounding_box' | 'geo_polygon' — Supported filter operators across database implementations.
          - `value` union, required — Value to compare against
            - DynamicValue — A value that should be dynamically resolved from the query request.
              - …
            - unknown
    - `NOT` union[], nullable — Logical NOT operation - all conditions must be false
      - union
        - LogicalOperatorInput — recursive
        - FilterCondition — Represents a single filter condition. Attributes: field: The field to filter on operator: The comparison operator value: The value to compare against
          - `field` string, required — Field name to filter on
          - `operator` 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'nin' | 'contains' | 'starts_with' | 'ends_with' | 'regex' | 'exists' | 'is_null' | 'text' | 'phrase' | 'geo_radius' | 'geo_bounding_box' | 'geo_polygon' — Supported filter operators across database implementations.
          - `value` union, required — Value to compare against
            - DynamicValue — A value that should be dynamically resolved from the query request.
              - …
            - unknown
    - `case_sensitive` boolean, nullable — Whether to perform case-sensitive matching
  - `sort` SortOption — Specifies how to sort query results. Attributes: field: Field to sort by direction: Sort direction (ascending or descending)
    - `field` string, required — Field to sort by, supports dot notation for nested fields
    - `direction` 'asc' | 'desc' — Sort direction options.
  - `sorts` object[], nullable — Sort options as a list of {field, direction} — the shape Studio datatables and the retriever list send. The first entry is the primary sort. Takes precedence over the singular `sort`.
  - `search` string, nullable — Search term for wildcard search across cluster_id, cluster_name, description, and other text fields

## Response `200`

Successful Response

- ListClustersResponse — Response model for listing clusters.
  - `results` ClusterMetadata[], required — List of cluster metadata
    - `cluster_id` string — Unique cluster job identifier
    - `cluster_name` string, required — Human-readable cluster name
    - `namespace_id` string, required — Namespace this cluster belongs to
    - `input_collections` string[], required — Source collection IDs that were clustered
    - `source_bucket_ids` string[], nullable — Source bucket IDs that the input collections originated from. Enables bucket lineage tracking.
    - `filters` object, nullable — Optional filters that were applied to pre-filter documents before clustering
    - `cluster_type` 'vector' | 'attribute', required — Type of clustering: vector (embedding-based) or attribute (metadata-based)
    - `feature_uris` string[], nullable — Feature URIs that were clustered (mixpeek://{extractor}@{version}/{output}). Only for vector clustering.
    - `multi_feature_strategy` string, nullable — Strategy used if multiple features (concatenate/independent/weighted). Only for vector clustering.
    - `learned_weights` object, nullable — Automatically learned feature weights (when multi_feature_strategy='weighted'). Keys are feature URIs, values are learned weights. Only populated after clustering execution completes.
    - `learning_quality_score` number, nullable — Clustering quality score from weight learning (e.g., silhouette score). Only populated when multi_feature_strategy='weighted' and weights were learned.
    - `effective_feature_method` string, nullable — Method for calculating cluster centroids (mean/median/medoid). Only for vector clustering.
    - `face_cluster_merge` FaceClusterMergeConfig — Configuration for the post-HDBSCAN face-identity merge pass. Enables an agglomerative merge after HDBSCAN labels are assigned but before centroid calculation. Two clusters merge when the centroid cosine meets the cosine threshold AND at least one of the spatial signals (bbox IoU on overlapping frames, scene Jaccard) also clears its threshold. Defaults target ArcFace 512d face embeddings at the brand-corpus scale (~10^4 faces, ~10^2 true identities).
      - `enabled` boolean — Run the merge pass. Set False to disable without removing the config.
      - `centroid_cosine_threshold` number — Minimum centroid cosine similarity for a candidate merge.
      - `bbox_iou_threshold` number — Minimum bbox IoU on overlapping frames to satisfy the spatial half.
      - `scene_jaccard_threshold` number — Minimum Jaccard similarity of scene-id sets to satisfy the spatial half.
      - `bbox_field` string — Document-payload field holding the face bbox (list/tuple of 4 floats).
      - `frame_field` string — Document-payload field holding the frame identifier used to pair bboxes.
      - `scene_field` string — Document-payload field holding the scene identifier used for Jaccard.
    - `sample_size` integer, nullable — Stored per-execution document cap. Populated from `vector_config.sample_size` at cluster creation and replayed into `ClusteringConfig` on every `POST /v1/clusters/{id}/execute` so re-runs stay consistent with the original config. When None, the export is uncapped (bounded by the engine's 100,000 safety limit). Only applies to vector clustering.
    - `preprocessing_steps` object[], nullable — Stored preprocessing steps from vector_config. Replayed into ClusteringConfig on every execute.
    - `hierarchical_vector` boolean, nullable — Whether recursive sub-clustering is enabled for vector clustering.
    - `max_hierarchy_depth` integer, nullable — Maximum recursion depth for hierarchical sub-clustering.
    - `vis_n_components` 2 | 3, nullable — Stored visualization dimensionality (2D or 3D). Replayed into ClusteringConfig on every execute as the default.
    - `layout_stability` 'none' | 'transform' | 'align', nullable — Stored layout-stability mode (LS-5) from vector_config.layout_stability. Replayed into ClusteringConfig on every execute. When unset, executions default to 'align' (keep the map stable across runs via post-hoc registration).
    - `clustered_attributes` string[], nullable — Attribute field names that were clustered. Only for attribute clustering.
    - `hierarchical_grouping` boolean, nullable — Whether hierarchical clustering was used. Only for attribute clustering.
    - `aggregation_method` string, nullable — Method for aggregating attributes (most_frequent/first/last). Only for attribute clustering.
    - `output_collection_ids` string[] — Collection IDs where cluster documents are stored. For single output: list with one collection ID. For per-feature output: list with one collection ID per feature.
    - `output_collection_names` string[] — Names of output collections. Corresponds to output_collection_ids.
    - `algorithm` string, nullable — Clustering algorithm used (hdbscan, kmeans, attribute_based, etc.)
    - `algorithm_params` object, nullable — Algorithm-specific parameters (not used for attribute_based)
    - `enrich_source` boolean — Whether source documents were enriched with cluster_id
    - `source_enrichment_config` SourceEnrichmentConfig — Configuration for enriching source collection documents with cluster assignments. When enrich_source_collection=True, cluster assignments are written back to the original source documents, similar to taxonomy enrichment. Uses flexible field mapping pattern to support any cluster result fields.
      - `field_mappings` EnrichmentFieldMapping[] — List of field mappings from cluster results to document fields. Default includes cluster_id and cluster_label. Can include: distance_to_centroid, member_count, keywords, visualization coords (x, y, z), etc.
        - `source_field` string, required — Field from cluster results to include. Available fields: cluster_id, cluster_label, distance_to_centroid, member_count, keywords, x, y, z (visualization coords), metadata.*
        - `target_field` string, required — Target field name in enriched document. Example: 'category_id' for cluster_id, 'product_category' for cluster_label
    - `llm_labeling` LLMLabelingOutput — Configuration for LLM-based cluster labeling. Supports multiple LLM providers with comprehensive model selection: - OpenAI: GPT-4o, GPT-4o-mini, GPT-4.1, O3-mini (best for quality) - Google: Gemini 2.5 Flash, Gemini 1.5 Flash (best for speed and cost) - Anthropic: Claude 3.5 Sonnet, Claude 3.5 Haiku (best for reasoning) All models are defined as enums and validated at API level.
      - `enabled` boolean — Whether to generate labels for clusters using LLM. When enabled, clusters will have semantic labels like 'High-Performance Laptops' instead of generic labels like 'Cluster 0'.
      - `labeling_inputs` LLMLabelingInputOutput — Input configuration for LLM-based cluster labeling. Supports flexible input mappings similar to retrievers and buckets, allowing multimodal inputs (text, images, videos, audio) for providers like Gemini that support native multimodal understanding. Examples: # Text-only labeling: LLMLabelingInput(input_mappings=[ InputMapping(input_key="headline", source_type="payload", path="headline"), InputMapping(input_key="description", source_type="payload", path="description") ]) # Multimodal labeling with images: LLMLabelingInput(input_mappings=[ InputMapping(input_key="text", source_type="payload", path="headline"), InputMapping(input_key="image_url", source_type="payload", path="thumbnail_url") ]) # Multimodal with video (for Gemini): LLMLabelingInput(input_mappings=[ InputMapping(input_key="text", source_type="payload", path="description"), InputMapping(input_key="video_url", source_type="payload", path="video_url") ])
        - `input_mappings` InputMapping[], required — Flexible input mappings for constructing LLM context. Supports multimodal inputs (text, image_url, video_url, audio_url). Each mapping specifies how to extract data from document payloads. At least one input mapping is required.
          - `input_key` string, required — Key used in the constructed inputs payload.
          - `source_type` 'payload' | 'literal' | 'vector' | 'blob' — Where the value for an input should be retrieved from.
          - `path` string, nullable — Dot-notation path when source_type is PAYLOAD or VECTOR. PAYLOAD paths resolve from the document's ROOT fields — each document/source_document dict IS the payload (e.g. path 'text' reads {'text': ...}); a {'payload': {...}} envelope is also accepted as a fallback.
          - `override` unknown
      - `provider` 'openai' | 'google' | 'anthropic' — Supported LLM providers for content generation. Each provider has different strengths, pricing, and multimodal capabilities. Choose based on your use case, performance requirements, and budget. Values: OPENAI: OpenAI GPT models (GPT-4o, GPT-4.1, O3-mini) - Best for: General purpose, vision tasks, structured outputs - Multimodal: Text, images - Performance: Fast (100-500ms), reliable - Cost: Moderate to high ($0.15-$10 per 1M tokens) - Use when: Need high-quality generation with vision support GOOGLE: Google Gemini models (Gemini 3.1 Flash Lite, Gemini 2.5 Pro) - Best for: Fast generation, video understanding, cost-efficiency - Multimodal: Text, images, video, audio, PDFs - Performance: Very fast (50-200ms) - Cost: Low to moderate ($0.075-$0.40 per 1M tokens) - Use when: Need video/audio/PDF support or cost-efficiency ANTHROPIC: Anthropic Claude models (Claude 3.5 Sonnet, Claude 3.5 Haiku) - Best for: Long context, complex reasoning, safety - Multimodal: Text, images - Performance: Moderate (200-800ms) - Cost: Moderate to high ($0.25-$15 per 1M tokens) - Use when: Need long context or complex reasoning Examples: - Use OPENAI for production with structured JSON outputs - Use GOOGLE for video summarization and cost-sensitive workloads - Use ANTHROPIC for complex reasoning with long documents
      - `model_name` union — REQUIRED when enabled=True. Specific LLM model to use for cluster labeling. All models are defined as enums for type safety. OpenAI Models (provider='openai'): - gpt-4o-2024-08-06: Highest quality, best for production ($2.50/$10 per 1M tokens) - gpt-4o-mini-2024-07-18: Cost-effective, recommended for most use cases ($0.15/$0.60 per 1M tokens) - gpt-4.1-2025-04-14: Latest model, future-proofed - gpt-4.1-mini-2025-04-14: Latest cost-optimized model - o3-mini-2025-01-31: Advanced reasoning, best for complex clustering Google Models (provider='google'): - gemini-2.5-flash-lite: Fastest, latest multimodal model, recommended ($0.15/$0.60 per 1M tokens) Anthropic Models (provider='anthropic'): - claude-3-5-sonnet-20241022: Best reasoning, 200K context ($3/$15 per 1M tokens) - claude-3-5-haiku-20241022: Fast, cost-effective ($0.25/$1.25 per 1M tokens) Recommendation: - Use gemini-2.5-flash-lite (DEFAULT) - multimodal support - Use gpt-4o-mini-2024-07-18 for OpenAI compatibility - Use gpt-4o-2024-08-06 for highest quality when cost is not a concern
        - 'gpt-4o-2024-08-06' | 'gpt-4o-mini-2024-07-18' | 'gpt-4.1-2025-04-14' | 'gpt-4.1-mini-2025-04-14' | 'o3-mini-2025-01-31' — OpenAI model identifiers for LLM generation. Models listed in order of capability and cost (highest to lowest). All models support vision (images) except O3-mini. Values: GPT_4O: Latest GPT-4 Omni model (2024-08-06) - Use for: Production, highest quality generation - Context: 128K tokens - Vision: Yes - Cost: $2.50/1M input, $10/1M output - Performance: 200-500ms per request - When to use: Need best quality, willing to pay premium GPT_41: GPT-4.1 (2025-04-14) - Use for: Future-proofed pipelines - Context: 128K tokens - Vision: Yes - Cost: TBD (expected similar to GPT-4o) - When to use: Want latest model features GPT_4O_MINI: Smaller, faster GPT-4 Omni (2024-07-18) - Use for: High-volume, cost-sensitive workloads - Context: 128K tokens - Vision: Yes - Cost: $0.15/1M input, $0.60/1M output - Performance: 100-200ms per request - When to use: Good balance of quality and cost GPT_41_MINI: Smaller GPT-4.1 (2025-04-14) - Use for: Future cost-optimized pipelines - Context: 128K tokens - Vision: Yes - Cost: TBD (expected similar to GPT-4o-mini) - When to use: Want latest features at lower cost O3_MINI: Reasoning-optimized model (2025-01-31) - Use for: Complex reasoning, math, code - Context: 200K tokens - Vision: No - Cost: TBD - When to use: Need advanced reasoning capabilities Examples: - Use GPT_4O for caption generation with images (best quality) - Use GPT_4O_MINI for high-volume video scene summarization (cost-effective) - Use O3_MINI for complex entity extraction requiring reasoning
        - 'gemini-2.5-flash-lite' | 'gemini-2.5-flash' | 'gemini-2.5-pro' | 'gemini-3.1-flash-lite' — Google Gemini model identifiers for LLM generation. Gemini models excel at multimodal understanding with best-in-class video support. All models support text, images, video, audio, and PDFs. Values: GEMINI_2_5_FLASH_LITE: Gemini 2.5 Flash Lite model (recommended, stable GA) - Use for: Fastest generation, cost-effective multimodal - Context: 1M tokens - Multimodal: Text, images, video, audio, PDFs - When to use: Default choice for all Gemini use cases GEMINI_2_5_PRO: Gemini 2.5 Pro model - Use for: Higher quality reasoning, complex tasks - Context: 1M tokens GEMINI_2_5_FLASH: Gemini 2.5 Flash model - Kept for backward compatibility. GEMINI_3_1_FLASH_LITE: Alias for gemini-2.5-flash-lite (backwards compat) - Note: gemini-3.1-flash-lite does NOT exist in Google's API. This value is mapped to gemini-2.5-flash-lite at runtime.
        - 'claude-sonnet-4-5-20250929' | 'claude-haiku-4-5-20251001' | 'claude-3-5-sonnet-20241022' | 'claude-3-5-haiku-20241022' — Anthropic Claude model identifiers for LLM generation. Claude models excel at long context, complex reasoning, and safety. All models support text and images. Values: CLAUDE_3_5_SONNET: Most capable Claude model - Use for: Complex reasoning, long documents, safety-critical - Context: 200K tokens - Vision: Yes - Cost: $3/1M input, $15/1M output - Performance: 300-800ms per request - When to use: Need best reasoning, safety, or long context CLAUDE_3_5_HAIKU: Fast, cost-effective Claude model - Use for: High-volume, quick summaries - Context: 200K tokens - Vision: Yes - Cost: $0.25/1M input, $1.25/1M output - Performance: 100-300ms per request - When to use: Good balance of quality and cost Examples: - Use CLAUDE_3_5_SONNET for complex entity extraction from contracts (best reasoning) - Use CLAUDE_3_5_HAIKU for high-volume content moderation (cost-effective)
      - `include_summary` boolean — Whether to generate cluster summaries
      - `include_keywords` boolean — Whether to extract keywords for clusters
      - `max_samples_per_cluster` integer, nullable — Maximum representative documents to send to LLM per cluster for semantic analysis. When null (default), automatically scales based on cluster size and spread — smaller/tighter clusters get fewer samples, larger/sparser clusters get more (range 3-20). Set explicitly to override with a fixed value.
      - `sample_text_max_length` integer — Maximum characters per document sample text
      - `sample_selection_strategy` 'nearest' | 'representative' — How representative documents are chosen for the labeling LLM. 'nearest' (default): the N members closest to the cluster centroid — maximally prototypical, but adjacent clusters can yield near-identical sample sets and therefore near-identical labels. 'representative': a mixed panel of ~40% nearest-to-centroid, ~40% diversity picks (farthest-point coverage of the cluster's extent), and ~20% high-density examples — differentiates similar clusters at the same sample count and LLM cost.
      - `use_embedding_dedup` boolean — Enable embedding-based label deduplication to prevent near-duplicate labels (requires sentence-transformers)
      - `embedding_similarity_threshold` number — Cosine similarity threshold for duplicate label detection (labels above this are considered duplicates)
      - `cache_ttl_seconds` integer — Time-to-live for cached labels in seconds. Labels for clusters with identical representative documents will be reused within this TTL window, reducing LLM API costs. Default: 604800 (7 days). Set to 0 to disable caching.
      - `labeling_context` string, nullable — OPTIONAL. Freeform domain context about the data being clustered, injected into the labeling prompt as a clearly-delimited 'Domain context provided by the user' block (LS-4). Unlike custom_prompt, this does NOT replace the default prompt — it grounds the default labeler so labels use the right domain vocabulary. Example: 'These are scenes from pharmaceutical TV ads' turns generic labels like 'People Talking Outdoors' into 'Patient Testimonial Scenes'. Max 2000 characters.
      - `custom_prompt` string, nullable — OPTIONAL. Custom prompt template for LLM labeling. NOT REQUIRED - uses default discriminative prompt if not provided. When provided, completely replaces the default prompt. Your custom prompt receives cluster information but you must format it yourself. Use when: - Need domain-specific labeling (e.g., medical, legal, technical) - Want different label format (e.g., emoji labels, code names) - Require specific output structure - Have custom business logic for categorization Default prompt includes: cluster document samples, forbidden labels for uniqueness, and JSON response format. See engine/clusters/labeling/prompts.py for reference. Example: 'Analyze these product clusters and generate SHORT category names (2-3 words max) focusing on product type and price range. Return JSON: [{"cluster_id": "cl_0", "label": "..."}]'
      - `response_shape` union — OPTIONAL. Define custom structured output for LLM labeling. NOT REQUIRED - uses default structure (label, summary, keywords) if not provided. When provided, LLM output will match this structure and be stored in cluster documents. Two modes supported: 1. Natural language prompt (string): Describe desired output in plain English - Service automatically infers JSON schema from your description - Example: 'Extract cluster category, confidence score (0-1), and top 3 representative terms' - Auto-generates schema with appropriate types (string, number, array, etc.) 2. Explicit JSON schema (dict): Provide complete JSON schema for output structure - Full control over output structure, types, and constraints - Example: {'type': 'object', 'properties': {'category': {'type': 'string'}, ...}} Use when: - Need custom metadata fields (confidence scores, sentiment, complexity) - Want domain-specific structure (taxonomy hierarchies, entity extractions) - Require specific data types (arrays, nested objects, enums) - Have downstream schema requirements Output fields are automatically added to cluster collection schema and stored in metadata. Default behavior (if not provided): label (string), summary (string), keywords (array of strings)
        - string
        - object
      - `parameters` object — Provider-specific parameters forwarded to the LLM service. For OpenAI: temperature, max_tokens, top_p, json_output, etc. For Google: temperature, top_k, max_output_tokens, json_output, etc.
    - `num_clusters` integer, nullable — Number of clusters found (excludes noise/outliers, populated after execution)
    - `num_documents_clustered` integer, nullable — Total documents processed
    - `execution_time_seconds` number, nullable — Time taken to complete clustering
    - `quality_metrics` object, nullable — Clustering quality metrics (silhouette_score, davies_bouldin_score, calinski_harabasz_score, etc.). Open diagnostic bag like ClusteringResult.metrics: mostly numeric, but the three-state degenerate flag (False | reason string) and its prose degenerate_detail are non-numeric, so the value type is Any. A float-only type 400'd every GET on a cluster whose run flagged a degenerate result (MC-1256's read-path sibling: the write side persisted the string, this read side then rejected it).
    - `hierarchy_detected` boolean — Whether implicit hierarchy was detected (multi-feature independent) or created (hierarchical attributes)
    - `parent_cluster_id` string, nullable — For child clusters in hierarchy
    - `child_cluster_ids` string[], nullable — For parent clusters
    - `hierarchy_relationships` object[], nullable — Parent-child relationships detected from cluster membership overlap
    - `status` 'PENDING' | 'QUEUED' | 'IN_PROGRESS' | 'PROCESSING' | 'COMPLETED' | 'COMPLETED_WITH_ERRORS' | 'FAILED' | 'CANCELED' | 'INTERRUPTED' | 'UNKNOWN' | 'SKIPPED' | 'DRAFT' | 'ACTIVE' | 'ARCHIVED' | 'SUSPENDED' | 'DEACTIVATED' — Enumeration of task statuses for tracking asynchronous operations. Task statuses indicate the current state of asynchronous operations like batch processing, object ingestion, clustering, and taxonomy execution. Status Categories: Operation Statuses: Track progress of async operations Lifecycle Statuses: Track entity state (buckets, collections, namespaces) Values: PENDING: Task is queued but has not started processing yet IN_PROGRESS: Task is currently being executed PROCESSING: Task is actively processing data (similar to IN_PROGRESS) COMPLETED: Task finished successfully with no errors COMPLETED_WITH_ERRORS: Task finished but some items failed (partial success) FAILED: Task encountered an error and could not complete CANCELED: Task was manually canceled by a user or system UNKNOWN: Task status could not be determined SKIPPED: Task was intentionally skipped DRAFT: Task is in draft state and not yet submitted ACTIVE: Entity is active and operational (for buckets, collections, etc.) ARCHIVED: Entity has been archived SUSPENDED: Entity has been temporarily suspended Terminal Statuses: COMPLETED, COMPLETED_WITH_ERRORS, FAILED, CANCELED are terminal statuses. Once a task reaches these states, it will not transition to another state. Partial Success Handling: COMPLETED_WITH_ERRORS indicates that the operation completed but some documents/items failed. The task result includes: - List of successful items - List of failed items with error details - Success rate percentage This allows clients to handle partial success scenarios appropriately. Polling Guidance: - Poll tasks in PENDING, QUEUED, IN_PROGRESS, or PROCESSING states - Stop polling when task reaches COMPLETED, COMPLETED_WITH_ERRORS, FAILED, or CANCELED - Use exponential backoff (1s → 30s) when polling
    - `error` string, nullable — Error message if cluster execution failed. Propagated from TaskService.
    - `failure_category` 'timeout' | 'infrastructure' | 'orphaned' | 'pipeline' | 'validation' | 'unknown' — Batch-level failure classification. Coarser-grained than ErrorCategory (which classifies individual object errors). FailureCategory is set on the batch itself to tell users *why the batch as a whole failed* — timeout, infra, orphan, pipeline, or unknown. Drives the "Batch failed: <category>" badge in Studio and lets callers distinguish retryable infra blips from genuine pipeline bugs without parsing human-readable strings.
    - `last_execution_task_id` string, nullable — Most recent task ID for this cluster
    - `last_run_id` string, nullable — Most recent execution run ID
    - `created_at` string, date-time — When cluster was created
    - `updated_at` string, date-time — When cluster was last updated
    - `last_executed_at` string, date-time, nullable — Last execution timestamp
    - `completed_at` string, date-time, nullable — When clustering completed successfully
    - `llm_labeling_errors` string[], nullable — List of errors encountered during LLM labeling (if any). Stored in MongoDB cluster metadata only, NOT in Qdrant cluster documents. Used to track LLM failures while allowing fallback labels to work.
    - `metadata` object — Additional user-defined metadata
  - `pagination` PaginationResponse, required — PaginationResponse. Cursor-based pagination response: - Use next_cursor for navigation - Total count fields only populated when include_total=true
    - `total` integer, nullable
    - `page` integer, nullable
    - `page_size` integer, nullable
    - `total_pages` integer, nullable
    - `next_page` string, nullable
    - `previous_page` string, nullable
    - `next_cursor` string, nullable
  - `total_count` integer, required — Total number of clusters matching the query
  - `stats` ClusterListStats — Aggregate statistics for a list of clusters.
    - `total_clusters` integer — Total number of clusters in the result
    - `total_documents` integer — Total number of documents across all clusters
    - `avg_documents_per_cluster` number — Average number of documents per cluster
    - `clusters_by_status` object — Count of clusters grouped by status

## Other responses

- `400` — Bad Request
- `401` — Unauthorized
- `403` — Forbidden
- `404` — Not Found
- `422` — Validation Error
- `500` — Internal Server Error

---

[API](https://skmtc.net/mixpeek/apis/mixpeek-api.md) · [All operations](https://skmtc.net/mixpeek/apis/mixpeek-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/mixpeek/mixpeek-api/versions/23e05292e326/schema)
