# Projects

Project management endpoints

## List Projects

> Retrieves a paginated list of projects accessible to the current user.\
> Returns only essential fields: \_id, name, description, organization, createdAt.<br>

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Projects","description":"Project management endpoints"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"PageParam":{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number (1-indexed)"},"LimitParam":{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Items per page (max 100)"},"SortParam":{"name":"sort","in":"query","schema":{"type":"string","default":"-createdAt"},"description":"Sort field (prefix with - for descending)"}},"schemas":{"ProjectListResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"projects":{"type":"array","items":{"$ref":"#/components/schemas/ProjectListItem"}},"total":{"type":"integer"}}}}},"ProjectListItem":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"organization":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"UnauthorizedError":{"description":"Unauthorized - invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/listProjects":{"get":{"tags":["Projects"],"summary":"List Projects","description":"Retrieves a paginated list of projects accessible to the current user.\nReturns only essential fields: _id, name, description, organization, createdAt.\n","operationId":"listProjects","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/LimitParam"},{"$ref":"#/components/parameters/SortParam"}],"responses":{"200":{"description":"Projects retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectListResponse"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"}}}}}}
```

## Create Project

> Creates a new annotation project with specified configuration

````json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Projects","description":"Project management endpoints"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"schemas":{"ProjectCreateRequest":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"description":"Project name"},"description":{"type":"string","description":"Project description"},"type":{"type":"string","description":"Project type","enum":["ango","pct","iframe"],"default":"ango"},"pctConfig":{"$ref":"#/components/schemas/PctConfig","description":"Point Cloud Tool configuration (required only when type is \"pct\")"}}},"PctConfig":{"type":"object","description":"Configuration specific to Point Cloud Tool (PCT) projects.\nThese settings control how 3D point cloud annotation behaves.\n\nExample:\n```json\n{\n  \"allowOverlapping\": false,\n  \"trackingMultipleSensors\": true,\n  \"segmentationMode\": false\n}\n```\n","properties":{"allowOverlapping":{"type":"boolean","description":"Allow overlapping 3D bounding boxes","default":false},"trackingMultipleSensors":{"type":"boolean","description":"Enable tracking across multiple LiDAR sensors","default":false},"segmentationMode":{"type":"boolean","description":"Enable segmentation mode for point clouds","default":false}}},"ProjectResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/Project"}}}}},"Project":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","enum":["ango","pct","iframe"],"default":"ango"},"owner":{"type":"string","description":"Owner email"},"organization":{"type":"string","description":"Organization ID"},"categorySchema":{"$ref":"#/components/schemas/CategorySchema"},"stages":{"type":"array","items":{"$ref":"#/components/schemas/Stage"}},"assignedTo":{"type":"array","items":{"$ref":"#/components/schemas/Assignee"}},"batches":{"type":"array","items":{"$ref":"#/components/schemas/Batch"}},"queueVersion":{"type":"number"},"assetCount":{"type":"integer"},"benchmarkEnabled":{"type":"boolean"},"benchmarkRatio":{"type":"number"},"instructions":{"type":"string","description":"Instructions URL"},"ocrLanguage":{"type":"string"},"idleTimeout":{"type":"number","description":"Idle timeout in seconds"},"projectPlugins":{"type":"object"},"pluginPresets":{"type":"array","items":{"type":"object"}},"errorCodesEnabled":{"type":"boolean"},"errorSchema":{"type":"object"},"exportStorageId":{"type":"string"},"exportStorageBucket":{"type":"string"},"exportStoragePath":{"type":"string"},"exportStorageEnabled":{"type":"boolean"},"taskSkipEnabled":{"type":"boolean"},"unassignSkippedTask":{"type":"boolean"},"gcSyncEnabled":{"type":"boolean"},"deleted":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CategorySchema":{"type":"object","description":"Label configuration schema that defines the annotation tools, classifications, and relations for a project.\nThis schema determines what annotation types are available to users and how they can label assets.\n\n**Note:** Schema structure varies between Ango and PCT projects.\n- Ango projects: Use standard annotation tools (bounding-box, polygon, etc.)\n- PCT projects: Use PCT tool type with markingTools array and nested classifications with PCT-specific fields\n","properties":{"tools":{"type":"array","description":"Array of annotation tools (bounding box, polygon, segmentation, etc.)","items":{"$ref":"#/components/schemas/Tool"}},"classifications":{"type":"array","description":"Array of classification questions (radio, checkbox, dropdown, text, etc.)","items":{"$ref":"#/components/schemas/Classification"}},"relations":{"type":"array","description":"Array of relation types that can connect annotations","items":{"$ref":"#/components/schemas/Relation"}}}},"Tool":{"type":"object","description":"Annotation tool configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this tool"},"title":{"type":"string","description":"Display name for the tool"},"tool":{"type":"string","description":"Type of annotation tool","enum":["bounding-box","polygon","polyline","point","rotated-bounding-box","segmentation","brush","medical-brush","ner","pdf","pct","angle"]},"required":{"type":"boolean","description":"Whether this annotation is required","default":false},"color":{"type":"string","description":"Hex color code for this annotation class","pattern":"^#[0-9A-Fa-f]{6}$"},"shortcutKey":{"type":"string","description":"Keyboard shortcut for quick selection"},"classifications":{"type":"array","description":"Nested classifications specific to this tool","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow creating multiple instances of this annotation","default":false},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data (for organizing exported annotations)"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"markingTools":{"type":"array","description":"(PCT only) List of marking tools enabled for this PCT tool.\nAvailable marking tools: polygon, polygon2d, polyline, polyline2d, cuboid, rectangle\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}},"truncate":{"type":"boolean","description":"(PCT only) Enable truncation for this tool","default":false},"presetCuboidDimensions":{"type":"boolean","description":"(PCT only) Enable preset cuboid dimensions","default":false},"cuboidLength":{"type":"string","description":"(PCT only) Preset cuboid length value (stored as string)"},"cuboidWidth":{"type":"string","description":"(PCT only) Preset cuboid width value (stored as string)"},"cuboidHeight":{"type":"string","description":"(PCT only) Preset cuboid height value (stored as string)"},"keypointWithVerticalLine":{"type":"boolean","description":"(PCT only) Enable keypoint with vertical line feature","default":false},"edgeLengthConstraint":{"type":"string","description":"(PCT only) Minimum edge length constraint (stored as string)"},"hasInstance":{"type":"boolean","description":"(PCT only) Enable instance tracking for this tool","default":false}}},"Classification":{"type":"object","description":"Classification question configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this classification"},"title":{"type":"string","description":"Question or label text"},"tool":{"type":"string","description":"Type of classification input (same as 'type')","enum":["radio","checkbox","single-dropdown","multi-dropdown","tree-dropdown","single-tree-dropdown","text","boolean"]},"color":{"type":"string","description":"Hex color code for this classification","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether answering this classification is required","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut key"},"columnField":{"type":"boolean","description":"Whether to show in column view","default":false},"frameSpecific":{"type":"boolean","description":"Whether classification is frame-specific (for videos)","default":false},"showDropdown":{"type":"boolean","description":"Whether to show as dropdown in UI","default":false},"richText":{"type":"boolean","description":"Whether to enable rich text input (for text type)","default":false},"regex":{"type":"string","nullable":true,"description":"Regular expression for text validation (for text type)"},"parentOptionId":{"type":"string","nullable":true,"description":"Parent option ID for nested classifications"},"options":{"type":"array","description":"Available options (not used for text type)","items":{"$ref":"#/components/schemas/ClassificationOption"}},"treeOptions":{"type":"array","description":"Tree-structured options (for tree-dropdown types)","items":{"type":"object"}},"classifications":{"type":"array","description":"Nested child classifications","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow multiple selections","default":false},"parentToolType":{"type":"string","description":"(PCT only) Parent tool type this classification belongs to"},"parentToolId":{"type":"string","description":"(PCT only) Parent tool schemaId this classification is associated with"},"attributeLevel":{"type":"string","description":"(PCT only) Level at which this attribute applies","enum":["Class Level","Instance Level"]},"defaultValue":{"description":"Default value for this classification (type varies based on classification tool type)","oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}]},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"attributeMode":{"type":"string","description":"(PCT only) Attribute mode determining how values persist across frames.\n- Time Varying: Value can change per frame\n- Constant: Single value for entire sequence\n- Sensor Specific: Different values per sensor\n","enum":["Time Varying","Constant","Sensor Specific"]},"associatedMarkingTool":{"type":"array","description":"(PCT only) Marking tools this classification is associated with.\nThis classification will only be available when using these marking tools.\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}}}},"ClassificationOption":{"type":"object","description":"Option for a classification question","required":["schemaId","value"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this option"},"value":{"type":"string","description":"Display text and internal value for this option"},"label":{"type":"string","description":"Alternative display text (deprecated, use 'value')"},"children":{"type":"array","description":"Nested classifications that appear when this option is selected","items":{"$ref":"#/components/schemas/Classification"}}}},"Relation":{"type":"object","description":"Relation type that can connect two annotations.\n\n**Relation Types:**\n- `one-to-one`: Direct connection between two annotations (Ango only)\n- `group`: Groups multiple annotations together (Ango only)\n- `one-to-many`: Parent-child hierarchical relationship (PCT only)\n\n**Note:** PCT projects support additional fields like `parentTool` and `childTools` for one-to-many relations.\n","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this relation"},"title":{"type":"string","description":"Display name for the relation"},"tool":{"type":"string","description":"Type of relation tool:\n- `one-to-one`: Direct 1:1 connection between annotations (Ango only)\n- `group`: Non-directional grouping of multiple annotations (Ango only)\n- `one-to-many`: Hierarchical parent-child relationship (PCT only)\n","enum":["one-to-one","group","one-to-many"]},"color":{"type":"string","description":"Hex color code for this relation","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether this relation must be used in annotations","default":false},"classifications":{"type":"array","description":"Nested classification questions attached to this relation.\nAllows adding metadata or attributes to the relationship itself.\n","default":[]},"multiple":{"type":"boolean","description":"Whether multiple instances of this relation can be created","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut to quickly create this relation"},"parentTool":{"type":"string","description":"(PCT only) For one-to-many relations, specifies the schemaId of the parent tool.\nOnly applicable when `tool: \"one-to-many\"`.\n"},"childTools":{"type":"array","description":"(PCT only) For one-to-many relations, specifies the schemaIds of allowed child tools.\nOnly applicable when `tool: \"one-to-many\"`.\n","items":{"type":"string"}}}},"Stage":{"type":"object","description":"Workflow stage configuration. Different stage types have different properties.\n- Label: Manual annotation stage\n- Review: QA/review stage\n- Logic: Conditional routing stage\n- Plugin: ML model integration stage\n- Webhook: External API callback stage\n- Consensus: Multi-annotator agreement stage\n- Hold: Pause stage\n- Start: Entry point (auto-forwards)\n- Complete: Terminal success stage\n- Archive: Terminal archive stage\n","required":["id","type"],"properties":{"id":{"type":"string","description":"Unique identifier for this stage"},"name":{"type":"string","description":"Display name for this stage"},"type":{"type":"string","description":"Type of stage","enum":["Label","Review","Logic","Plugin","Webhook","Consensus","Hold","Start","Complete","Archive"]},"next":{"type":"array","items":{"type":"string"},"description":"Array of next stage IDs (for Logic stages, order matters)"},"position":{"type":"object","description":"Position in workflow diagram UI","properties":{"x":{"type":"number"},"y":{"type":"number"}}},"assignedTo":{"type":"array","description":"Users assigned to work on this stage (Label/Review stages)","items":{"type":"string"}},"rememberAssignee":{"type":"boolean","description":"Auto-assign to previous stage's user (sticky assignment)","default":false},"logic":{"$ref":"#/components/schemas/LogicConfig","description":"Logic routing configuration (Logic stages only)"},"pluginId":{"type":"string","description":"Plugin ID to execute (Plugin stages only)"},"pluginConfig":{"type":"object","description":"Plugin-specific configuration (Plugin stages only)"},"webhook":{"$ref":"#/components/schemas/WebhookConfig","description":"Webhook configuration (Webhook stages only)"},"consensusConfig":{"$ref":"#/components/schemas/ConsensusConfig","description":"Consensus configuration (Consensus stages only)"},"readOnly":{"type":"boolean","description":"Whether this stage is read-only (users can view but not edit)","default":false},"preventRequeue":{"type":"boolean","description":"Prevent tasks from being requeued to this stage","default":false},"autoForward":{"type":"boolean","description":"Automatically advance to next stage without user action","default":true},"consensusId":{"type":"string","description":"Links stage to a consensus stage (used in consensus workflows)"},"consensusDynamic":{"type":"boolean","description":"Dynamic vs static consensus stage","default":false}}},"LogicConfig":{"type":"object","description":"Logic stage routing configuration. Routes tasks based on conditions.\nConditions are evaluated in order, first match wins.\n","properties":{"type":{"type":"string","description":"Type of logic routing","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Default value (usually empty)"},"conditions":{"type":"array","description":"Array of routing conditions","items":{"$ref":"#/components/schemas/LogicCondition"}}}},"LogicCondition":{"type":"object","description":"Individual routing condition for Logic stages","properties":{"type":{"type":"string","description":"Type of condition","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Condition-specific value","properties":{"tools":{"type":"array","description":"Tool filters (AnnotationType logic)","items":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"},"description":"Annotation filters:\n- exists___<schemaId>: Annotation must exist\n- not-exist___<schemaId>: Annotation must NOT exist\n"}}}},"emails":{"type":"array","description":"User emails (Annotator logic)","items":{"type":"string"}},"sampleRate":{"type":"number","description":"Sample rate 0-1 (RandomSample logic)","minimum":0,"maximum":1},"duration":{"type":"number","description":"Duration in milliseconds (Duration logic)"},"operator":{"type":"string","description":"Comparison operator for Duration","enum":["lt","gt","eq"]},"batches":{"type":"array","description":"Batch names (Batch logic)","items":{"type":"string"}}}},"index":{"type":"number","description":"Index of next stage in parent's next array"}}},"WebhookConfig":{"type":"object","description":"Webhook configuration for external API integration","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Webhook endpoint URL"},"method":{"type":"string","description":"HTTP method","enum":["POST","PUT"],"default":"POST"},"authType":{"type":"string","description":"Authentication type","enum":["no_auth","secret","bearer_token"],"default":"no_auth"},"secret":{"type":"string","description":"Secret for HMAC signature (authType=secret)"},"token":{"type":"string","description":"Bearer token (authType=bearer_token)"},"timeout":{"type":"number","description":"Timeout in milliseconds","default":30000},"retryCount":{"type":"number","description":"Number of retry attempts","default":3}}},"ConsensusConfig":{"type":"object","description":"Consensus configuration for multi-annotator agreement","properties":{"version":{"type":"number","description":"Consensus algorithm version (1 or 2, v2 recommended)","enum":[1,2],"default":2},"threshold":{"type":"number","description":"Minimum agreement score (0-1) required to pass","minimum":0,"maximum":1},"adjudicationMethod":{"type":"string","description":"Method for resolving disagreements","enum":["majority","union","intersection","first"],"default":"majority"},"dynamicConsensus":{"type":"boolean","description":"Add more copies if threshold not met","default":false},"minCopies":{"type":"number","description":"Minimum number of consensus copies","minimum":2,"default":2},"maxCopies":{"type":"number","description":"Maximum number of consensus copies (dynamic consensus)","default":5}}},"Assignee":{"type":"object","properties":{"assignee":{"type":"string","description":"User email"},"role":{"type":"string","enum":["Manager","Labeler","Reviewer","Lead"]}}},"Batch":{"type":"object","required":["name"],"properties":{"_id":{"type":"string","description":"Batch ID (auto-generated if not provided)"},"name":{"type":"string","description":"Batch name"}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"BadRequestError":{"description":"Bad request - validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"UnauthorizedError":{"description":"Unauthorized - invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/project":{"post":{"tags":["Projects"],"summary":"Create Project","description":"Creates a new annotation project with specified configuration","operationId":"createProject","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectCreateRequest"}}}},"responses":{"201":{"description":"Project created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"}}}}}}
````

## Get Project Details

> Retrieves complete details for a specific project

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Projects","description":"Project management endpoints"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"ProjectIdParam":{"name":"projectId","in":"path","required":true,"schema":{"type":"string"},"description":"Project ID"}},"schemas":{"ProjectResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/Project"}}}}},"Project":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","enum":["ango","pct","iframe"],"default":"ango"},"owner":{"type":"string","description":"Owner email"},"organization":{"type":"string","description":"Organization ID"},"categorySchema":{"$ref":"#/components/schemas/CategorySchema"},"stages":{"type":"array","items":{"$ref":"#/components/schemas/Stage"}},"assignedTo":{"type":"array","items":{"$ref":"#/components/schemas/Assignee"}},"batches":{"type":"array","items":{"$ref":"#/components/schemas/Batch"}},"queueVersion":{"type":"number"},"assetCount":{"type":"integer"},"benchmarkEnabled":{"type":"boolean"},"benchmarkRatio":{"type":"number"},"instructions":{"type":"string","description":"Instructions URL"},"ocrLanguage":{"type":"string"},"idleTimeout":{"type":"number","description":"Idle timeout in seconds"},"projectPlugins":{"type":"object"},"pluginPresets":{"type":"array","items":{"type":"object"}},"errorCodesEnabled":{"type":"boolean"},"errorSchema":{"type":"object"},"exportStorageId":{"type":"string"},"exportStorageBucket":{"type":"string"},"exportStoragePath":{"type":"string"},"exportStorageEnabled":{"type":"boolean"},"taskSkipEnabled":{"type":"boolean"},"unassignSkippedTask":{"type":"boolean"},"gcSyncEnabled":{"type":"boolean"},"deleted":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CategorySchema":{"type":"object","description":"Label configuration schema that defines the annotation tools, classifications, and relations for a project.\nThis schema determines what annotation types are available to users and how they can label assets.\n\n**Note:** Schema structure varies between Ango and PCT projects.\n- Ango projects: Use standard annotation tools (bounding-box, polygon, etc.)\n- PCT projects: Use PCT tool type with markingTools array and nested classifications with PCT-specific fields\n","properties":{"tools":{"type":"array","description":"Array of annotation tools (bounding box, polygon, segmentation, etc.)","items":{"$ref":"#/components/schemas/Tool"}},"classifications":{"type":"array","description":"Array of classification questions (radio, checkbox, dropdown, text, etc.)","items":{"$ref":"#/components/schemas/Classification"}},"relations":{"type":"array","description":"Array of relation types that can connect annotations","items":{"$ref":"#/components/schemas/Relation"}}}},"Tool":{"type":"object","description":"Annotation tool configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this tool"},"title":{"type":"string","description":"Display name for the tool"},"tool":{"type":"string","description":"Type of annotation tool","enum":["bounding-box","polygon","polyline","point","rotated-bounding-box","segmentation","brush","medical-brush","ner","pdf","pct","angle"]},"required":{"type":"boolean","description":"Whether this annotation is required","default":false},"color":{"type":"string","description":"Hex color code for this annotation class","pattern":"^#[0-9A-Fa-f]{6}$"},"shortcutKey":{"type":"string","description":"Keyboard shortcut for quick selection"},"classifications":{"type":"array","description":"Nested classifications specific to this tool","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow creating multiple instances of this annotation","default":false},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data (for organizing exported annotations)"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"markingTools":{"type":"array","description":"(PCT only) List of marking tools enabled for this PCT tool.\nAvailable marking tools: polygon, polygon2d, polyline, polyline2d, cuboid, rectangle\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}},"truncate":{"type":"boolean","description":"(PCT only) Enable truncation for this tool","default":false},"presetCuboidDimensions":{"type":"boolean","description":"(PCT only) Enable preset cuboid dimensions","default":false},"cuboidLength":{"type":"string","description":"(PCT only) Preset cuboid length value (stored as string)"},"cuboidWidth":{"type":"string","description":"(PCT only) Preset cuboid width value (stored as string)"},"cuboidHeight":{"type":"string","description":"(PCT only) Preset cuboid height value (stored as string)"},"keypointWithVerticalLine":{"type":"boolean","description":"(PCT only) Enable keypoint with vertical line feature","default":false},"edgeLengthConstraint":{"type":"string","description":"(PCT only) Minimum edge length constraint (stored as string)"},"hasInstance":{"type":"boolean","description":"(PCT only) Enable instance tracking for this tool","default":false}}},"Classification":{"type":"object","description":"Classification question configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this classification"},"title":{"type":"string","description":"Question or label text"},"tool":{"type":"string","description":"Type of classification input (same as 'type')","enum":["radio","checkbox","single-dropdown","multi-dropdown","tree-dropdown","single-tree-dropdown","text","boolean"]},"color":{"type":"string","description":"Hex color code for this classification","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether answering this classification is required","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut key"},"columnField":{"type":"boolean","description":"Whether to show in column view","default":false},"frameSpecific":{"type":"boolean","description":"Whether classification is frame-specific (for videos)","default":false},"showDropdown":{"type":"boolean","description":"Whether to show as dropdown in UI","default":false},"richText":{"type":"boolean","description":"Whether to enable rich text input (for text type)","default":false},"regex":{"type":"string","nullable":true,"description":"Regular expression for text validation (for text type)"},"parentOptionId":{"type":"string","nullable":true,"description":"Parent option ID for nested classifications"},"options":{"type":"array","description":"Available options (not used for text type)","items":{"$ref":"#/components/schemas/ClassificationOption"}},"treeOptions":{"type":"array","description":"Tree-structured options (for tree-dropdown types)","items":{"type":"object"}},"classifications":{"type":"array","description":"Nested child classifications","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow multiple selections","default":false},"parentToolType":{"type":"string","description":"(PCT only) Parent tool type this classification belongs to"},"parentToolId":{"type":"string","description":"(PCT only) Parent tool schemaId this classification is associated with"},"attributeLevel":{"type":"string","description":"(PCT only) Level at which this attribute applies","enum":["Class Level","Instance Level"]},"defaultValue":{"description":"Default value for this classification (type varies based on classification tool type)","oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}]},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"attributeMode":{"type":"string","description":"(PCT only) Attribute mode determining how values persist across frames.\n- Time Varying: Value can change per frame\n- Constant: Single value for entire sequence\n- Sensor Specific: Different values per sensor\n","enum":["Time Varying","Constant","Sensor Specific"]},"associatedMarkingTool":{"type":"array","description":"(PCT only) Marking tools this classification is associated with.\nThis classification will only be available when using these marking tools.\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}}}},"ClassificationOption":{"type":"object","description":"Option for a classification question","required":["schemaId","value"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this option"},"value":{"type":"string","description":"Display text and internal value for this option"},"label":{"type":"string","description":"Alternative display text (deprecated, use 'value')"},"children":{"type":"array","description":"Nested classifications that appear when this option is selected","items":{"$ref":"#/components/schemas/Classification"}}}},"Relation":{"type":"object","description":"Relation type that can connect two annotations.\n\n**Relation Types:**\n- `one-to-one`: Direct connection between two annotations (Ango only)\n- `group`: Groups multiple annotations together (Ango only)\n- `one-to-many`: Parent-child hierarchical relationship (PCT only)\n\n**Note:** PCT projects support additional fields like `parentTool` and `childTools` for one-to-many relations.\n","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this relation"},"title":{"type":"string","description":"Display name for the relation"},"tool":{"type":"string","description":"Type of relation tool:\n- `one-to-one`: Direct 1:1 connection between annotations (Ango only)\n- `group`: Non-directional grouping of multiple annotations (Ango only)\n- `one-to-many`: Hierarchical parent-child relationship (PCT only)\n","enum":["one-to-one","group","one-to-many"]},"color":{"type":"string","description":"Hex color code for this relation","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether this relation must be used in annotations","default":false},"classifications":{"type":"array","description":"Nested classification questions attached to this relation.\nAllows adding metadata or attributes to the relationship itself.\n","default":[]},"multiple":{"type":"boolean","description":"Whether multiple instances of this relation can be created","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut to quickly create this relation"},"parentTool":{"type":"string","description":"(PCT only) For one-to-many relations, specifies the schemaId of the parent tool.\nOnly applicable when `tool: \"one-to-many\"`.\n"},"childTools":{"type":"array","description":"(PCT only) For one-to-many relations, specifies the schemaIds of allowed child tools.\nOnly applicable when `tool: \"one-to-many\"`.\n","items":{"type":"string"}}}},"Stage":{"type":"object","description":"Workflow stage configuration. Different stage types have different properties.\n- Label: Manual annotation stage\n- Review: QA/review stage\n- Logic: Conditional routing stage\n- Plugin: ML model integration stage\n- Webhook: External API callback stage\n- Consensus: Multi-annotator agreement stage\n- Hold: Pause stage\n- Start: Entry point (auto-forwards)\n- Complete: Terminal success stage\n- Archive: Terminal archive stage\n","required":["id","type"],"properties":{"id":{"type":"string","description":"Unique identifier for this stage"},"name":{"type":"string","description":"Display name for this stage"},"type":{"type":"string","description":"Type of stage","enum":["Label","Review","Logic","Plugin","Webhook","Consensus","Hold","Start","Complete","Archive"]},"next":{"type":"array","items":{"type":"string"},"description":"Array of next stage IDs (for Logic stages, order matters)"},"position":{"type":"object","description":"Position in workflow diagram UI","properties":{"x":{"type":"number"},"y":{"type":"number"}}},"assignedTo":{"type":"array","description":"Users assigned to work on this stage (Label/Review stages)","items":{"type":"string"}},"rememberAssignee":{"type":"boolean","description":"Auto-assign to previous stage's user (sticky assignment)","default":false},"logic":{"$ref":"#/components/schemas/LogicConfig","description":"Logic routing configuration (Logic stages only)"},"pluginId":{"type":"string","description":"Plugin ID to execute (Plugin stages only)"},"pluginConfig":{"type":"object","description":"Plugin-specific configuration (Plugin stages only)"},"webhook":{"$ref":"#/components/schemas/WebhookConfig","description":"Webhook configuration (Webhook stages only)"},"consensusConfig":{"$ref":"#/components/schemas/ConsensusConfig","description":"Consensus configuration (Consensus stages only)"},"readOnly":{"type":"boolean","description":"Whether this stage is read-only (users can view but not edit)","default":false},"preventRequeue":{"type":"boolean","description":"Prevent tasks from being requeued to this stage","default":false},"autoForward":{"type":"boolean","description":"Automatically advance to next stage without user action","default":true},"consensusId":{"type":"string","description":"Links stage to a consensus stage (used in consensus workflows)"},"consensusDynamic":{"type":"boolean","description":"Dynamic vs static consensus stage","default":false}}},"LogicConfig":{"type":"object","description":"Logic stage routing configuration. Routes tasks based on conditions.\nConditions are evaluated in order, first match wins.\n","properties":{"type":{"type":"string","description":"Type of logic routing","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Default value (usually empty)"},"conditions":{"type":"array","description":"Array of routing conditions","items":{"$ref":"#/components/schemas/LogicCondition"}}}},"LogicCondition":{"type":"object","description":"Individual routing condition for Logic stages","properties":{"type":{"type":"string","description":"Type of condition","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Condition-specific value","properties":{"tools":{"type":"array","description":"Tool filters (AnnotationType logic)","items":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"},"description":"Annotation filters:\n- exists___<schemaId>: Annotation must exist\n- not-exist___<schemaId>: Annotation must NOT exist\n"}}}},"emails":{"type":"array","description":"User emails (Annotator logic)","items":{"type":"string"}},"sampleRate":{"type":"number","description":"Sample rate 0-1 (RandomSample logic)","minimum":0,"maximum":1},"duration":{"type":"number","description":"Duration in milliseconds (Duration logic)"},"operator":{"type":"string","description":"Comparison operator for Duration","enum":["lt","gt","eq"]},"batches":{"type":"array","description":"Batch names (Batch logic)","items":{"type":"string"}}}},"index":{"type":"number","description":"Index of next stage in parent's next array"}}},"WebhookConfig":{"type":"object","description":"Webhook configuration for external API integration","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Webhook endpoint URL"},"method":{"type":"string","description":"HTTP method","enum":["POST","PUT"],"default":"POST"},"authType":{"type":"string","description":"Authentication type","enum":["no_auth","secret","bearer_token"],"default":"no_auth"},"secret":{"type":"string","description":"Secret for HMAC signature (authType=secret)"},"token":{"type":"string","description":"Bearer token (authType=bearer_token)"},"timeout":{"type":"number","description":"Timeout in milliseconds","default":30000},"retryCount":{"type":"number","description":"Number of retry attempts","default":3}}},"ConsensusConfig":{"type":"object","description":"Consensus configuration for multi-annotator agreement","properties":{"version":{"type":"number","description":"Consensus algorithm version (1 or 2, v2 recommended)","enum":[1,2],"default":2},"threshold":{"type":"number","description":"Minimum agreement score (0-1) required to pass","minimum":0,"maximum":1},"adjudicationMethod":{"type":"string","description":"Method for resolving disagreements","enum":["majority","union","intersection","first"],"default":"majority"},"dynamicConsensus":{"type":"boolean","description":"Add more copies if threshold not met","default":false},"minCopies":{"type":"number","description":"Minimum number of consensus copies","minimum":2,"default":2},"maxCopies":{"type":"number","description":"Maximum number of consensus copies (dynamic consensus)","default":5}}},"Assignee":{"type":"object","properties":{"assignee":{"type":"string","description":"User email"},"role":{"type":"string","enum":["Manager","Labeler","Reviewer","Lead"]}}},"Batch":{"type":"object","required":["name"],"properties":{"_id":{"type":"string","description":"Batch ID (auto-generated if not provided)"},"name":{"type":"string","description":"Batch name"}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"UnauthorizedError":{"description":"Unauthorized - invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFoundError":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/project/{projectId}":{"get":{"tags":["Projects"],"summary":"Get Project Details","description":"Retrieves complete details for a specific project","operationId":"getProject","parameters":[{"$ref":"#/components/parameters/ProjectIdParam"}],"responses":{"200":{"description":"Project details retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"}}}}}}
```

## Update Project

> Updates project configuration and settings

````json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Projects","description":"Project management endpoints"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"ProjectIdParam":{"name":"projectId","in":"path","required":true,"schema":{"type":"string"},"description":"Project ID"}},"schemas":{"ProjectUpdateRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":"string"},"categorySchema":{"$ref":"#/components/schemas/CategorySchema"},"stages":{"type":"array","items":{"$ref":"#/components/schemas/Stage"}},"batches":{"type":"array","items":{"$ref":"#/components/schemas/Batch"}},"benchmarkEnabled":{"type":"boolean"},"benchmarkRatio":{"type":"number"},"instructions":{"type":"string"},"ocrLanguage":{"type":"string"},"idleTimeout":{"type":"number"},"projectPlugins":{"type":"object"},"pluginPresets":{"type":"array","items":{"type":"object"}},"errorCodesEnabled":{"type":"boolean"},"errorSchema":{"type":"object"},"exportStorageId":{"type":"string"},"exportStorageBucket":{"type":"string"},"exportStoragePath":{"type":"string"},"exportStorageEnabled":{"type":"boolean"},"taskSkipEnabled":{"type":"boolean"},"unassignSkippedTask":{"type":"boolean"},"gcSyncEnabled":{"type":"boolean"},"pctConfig":{"$ref":"#/components/schemas/PctConfig","description":"Point Cloud Tool configuration (only for pct project type)"},"deleted":{"type":"boolean"}}},"CategorySchema":{"type":"object","description":"Label configuration schema that defines the annotation tools, classifications, and relations for a project.\nThis schema determines what annotation types are available to users and how they can label assets.\n\n**Note:** Schema structure varies between Ango and PCT projects.\n- Ango projects: Use standard annotation tools (bounding-box, polygon, etc.)\n- PCT projects: Use PCT tool type with markingTools array and nested classifications with PCT-specific fields\n","properties":{"tools":{"type":"array","description":"Array of annotation tools (bounding box, polygon, segmentation, etc.)","items":{"$ref":"#/components/schemas/Tool"}},"classifications":{"type":"array","description":"Array of classification questions (radio, checkbox, dropdown, text, etc.)","items":{"$ref":"#/components/schemas/Classification"}},"relations":{"type":"array","description":"Array of relation types that can connect annotations","items":{"$ref":"#/components/schemas/Relation"}}}},"Tool":{"type":"object","description":"Annotation tool configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this tool"},"title":{"type":"string","description":"Display name for the tool"},"tool":{"type":"string","description":"Type of annotation tool","enum":["bounding-box","polygon","polyline","point","rotated-bounding-box","segmentation","brush","medical-brush","ner","pdf","pct","angle"]},"required":{"type":"boolean","description":"Whether this annotation is required","default":false},"color":{"type":"string","description":"Hex color code for this annotation class","pattern":"^#[0-9A-Fa-f]{6}$"},"shortcutKey":{"type":"string","description":"Keyboard shortcut for quick selection"},"classifications":{"type":"array","description":"Nested classifications specific to this tool","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow creating multiple instances of this annotation","default":false},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data (for organizing exported annotations)"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"markingTools":{"type":"array","description":"(PCT only) List of marking tools enabled for this PCT tool.\nAvailable marking tools: polygon, polygon2d, polyline, polyline2d, cuboid, rectangle\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}},"truncate":{"type":"boolean","description":"(PCT only) Enable truncation for this tool","default":false},"presetCuboidDimensions":{"type":"boolean","description":"(PCT only) Enable preset cuboid dimensions","default":false},"cuboidLength":{"type":"string","description":"(PCT only) Preset cuboid length value (stored as string)"},"cuboidWidth":{"type":"string","description":"(PCT only) Preset cuboid width value (stored as string)"},"cuboidHeight":{"type":"string","description":"(PCT only) Preset cuboid height value (stored as string)"},"keypointWithVerticalLine":{"type":"boolean","description":"(PCT only) Enable keypoint with vertical line feature","default":false},"edgeLengthConstraint":{"type":"string","description":"(PCT only) Minimum edge length constraint (stored as string)"},"hasInstance":{"type":"boolean","description":"(PCT only) Enable instance tracking for this tool","default":false}}},"Classification":{"type":"object","description":"Classification question configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this classification"},"title":{"type":"string","description":"Question or label text"},"tool":{"type":"string","description":"Type of classification input (same as 'type')","enum":["radio","checkbox","single-dropdown","multi-dropdown","tree-dropdown","single-tree-dropdown","text","boolean"]},"color":{"type":"string","description":"Hex color code for this classification","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether answering this classification is required","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut key"},"columnField":{"type":"boolean","description":"Whether to show in column view","default":false},"frameSpecific":{"type":"boolean","description":"Whether classification is frame-specific (for videos)","default":false},"showDropdown":{"type":"boolean","description":"Whether to show as dropdown in UI","default":false},"richText":{"type":"boolean","description":"Whether to enable rich text input (for text type)","default":false},"regex":{"type":"string","nullable":true,"description":"Regular expression for text validation (for text type)"},"parentOptionId":{"type":"string","nullable":true,"description":"Parent option ID for nested classifications"},"options":{"type":"array","description":"Available options (not used for text type)","items":{"$ref":"#/components/schemas/ClassificationOption"}},"treeOptions":{"type":"array","description":"Tree-structured options (for tree-dropdown types)","items":{"type":"object"}},"classifications":{"type":"array","description":"Nested child classifications","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow multiple selections","default":false},"parentToolType":{"type":"string","description":"(PCT only) Parent tool type this classification belongs to"},"parentToolId":{"type":"string","description":"(PCT only) Parent tool schemaId this classification is associated with"},"attributeLevel":{"type":"string","description":"(PCT only) Level at which this attribute applies","enum":["Class Level","Instance Level"]},"defaultValue":{"description":"Default value for this classification (type varies based on classification tool type)","oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}]},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"attributeMode":{"type":"string","description":"(PCT only) Attribute mode determining how values persist across frames.\n- Time Varying: Value can change per frame\n- Constant: Single value for entire sequence\n- Sensor Specific: Different values per sensor\n","enum":["Time Varying","Constant","Sensor Specific"]},"associatedMarkingTool":{"type":"array","description":"(PCT only) Marking tools this classification is associated with.\nThis classification will only be available when using these marking tools.\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}}}},"ClassificationOption":{"type":"object","description":"Option for a classification question","required":["schemaId","value"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this option"},"value":{"type":"string","description":"Display text and internal value for this option"},"label":{"type":"string","description":"Alternative display text (deprecated, use 'value')"},"children":{"type":"array","description":"Nested classifications that appear when this option is selected","items":{"$ref":"#/components/schemas/Classification"}}}},"Relation":{"type":"object","description":"Relation type that can connect two annotations.\n\n**Relation Types:**\n- `one-to-one`: Direct connection between two annotations (Ango only)\n- `group`: Groups multiple annotations together (Ango only)\n- `one-to-many`: Parent-child hierarchical relationship (PCT only)\n\n**Note:** PCT projects support additional fields like `parentTool` and `childTools` for one-to-many relations.\n","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this relation"},"title":{"type":"string","description":"Display name for the relation"},"tool":{"type":"string","description":"Type of relation tool:\n- `one-to-one`: Direct 1:1 connection between annotations (Ango only)\n- `group`: Non-directional grouping of multiple annotations (Ango only)\n- `one-to-many`: Hierarchical parent-child relationship (PCT only)\n","enum":["one-to-one","group","one-to-many"]},"color":{"type":"string","description":"Hex color code for this relation","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether this relation must be used in annotations","default":false},"classifications":{"type":"array","description":"Nested classification questions attached to this relation.\nAllows adding metadata or attributes to the relationship itself.\n","default":[]},"multiple":{"type":"boolean","description":"Whether multiple instances of this relation can be created","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut to quickly create this relation"},"parentTool":{"type":"string","description":"(PCT only) For one-to-many relations, specifies the schemaId of the parent tool.\nOnly applicable when `tool: \"one-to-many\"`.\n"},"childTools":{"type":"array","description":"(PCT only) For one-to-many relations, specifies the schemaIds of allowed child tools.\nOnly applicable when `tool: \"one-to-many\"`.\n","items":{"type":"string"}}}},"Stage":{"type":"object","description":"Workflow stage configuration. Different stage types have different properties.\n- Label: Manual annotation stage\n- Review: QA/review stage\n- Logic: Conditional routing stage\n- Plugin: ML model integration stage\n- Webhook: External API callback stage\n- Consensus: Multi-annotator agreement stage\n- Hold: Pause stage\n- Start: Entry point (auto-forwards)\n- Complete: Terminal success stage\n- Archive: Terminal archive stage\n","required":["id","type"],"properties":{"id":{"type":"string","description":"Unique identifier for this stage"},"name":{"type":"string","description":"Display name for this stage"},"type":{"type":"string","description":"Type of stage","enum":["Label","Review","Logic","Plugin","Webhook","Consensus","Hold","Start","Complete","Archive"]},"next":{"type":"array","items":{"type":"string"},"description":"Array of next stage IDs (for Logic stages, order matters)"},"position":{"type":"object","description":"Position in workflow diagram UI","properties":{"x":{"type":"number"},"y":{"type":"number"}}},"assignedTo":{"type":"array","description":"Users assigned to work on this stage (Label/Review stages)","items":{"type":"string"}},"rememberAssignee":{"type":"boolean","description":"Auto-assign to previous stage's user (sticky assignment)","default":false},"logic":{"$ref":"#/components/schemas/LogicConfig","description":"Logic routing configuration (Logic stages only)"},"pluginId":{"type":"string","description":"Plugin ID to execute (Plugin stages only)"},"pluginConfig":{"type":"object","description":"Plugin-specific configuration (Plugin stages only)"},"webhook":{"$ref":"#/components/schemas/WebhookConfig","description":"Webhook configuration (Webhook stages only)"},"consensusConfig":{"$ref":"#/components/schemas/ConsensusConfig","description":"Consensus configuration (Consensus stages only)"},"readOnly":{"type":"boolean","description":"Whether this stage is read-only (users can view but not edit)","default":false},"preventRequeue":{"type":"boolean","description":"Prevent tasks from being requeued to this stage","default":false},"autoForward":{"type":"boolean","description":"Automatically advance to next stage without user action","default":true},"consensusId":{"type":"string","description":"Links stage to a consensus stage (used in consensus workflows)"},"consensusDynamic":{"type":"boolean","description":"Dynamic vs static consensus stage","default":false}}},"LogicConfig":{"type":"object","description":"Logic stage routing configuration. Routes tasks based on conditions.\nConditions are evaluated in order, first match wins.\n","properties":{"type":{"type":"string","description":"Type of logic routing","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Default value (usually empty)"},"conditions":{"type":"array","description":"Array of routing conditions","items":{"$ref":"#/components/schemas/LogicCondition"}}}},"LogicCondition":{"type":"object","description":"Individual routing condition for Logic stages","properties":{"type":{"type":"string","description":"Type of condition","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Condition-specific value","properties":{"tools":{"type":"array","description":"Tool filters (AnnotationType logic)","items":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"},"description":"Annotation filters:\n- exists___<schemaId>: Annotation must exist\n- not-exist___<schemaId>: Annotation must NOT exist\n"}}}},"emails":{"type":"array","description":"User emails (Annotator logic)","items":{"type":"string"}},"sampleRate":{"type":"number","description":"Sample rate 0-1 (RandomSample logic)","minimum":0,"maximum":1},"duration":{"type":"number","description":"Duration in milliseconds (Duration logic)"},"operator":{"type":"string","description":"Comparison operator for Duration","enum":["lt","gt","eq"]},"batches":{"type":"array","description":"Batch names (Batch logic)","items":{"type":"string"}}}},"index":{"type":"number","description":"Index of next stage in parent's next array"}}},"WebhookConfig":{"type":"object","description":"Webhook configuration for external API integration","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Webhook endpoint URL"},"method":{"type":"string","description":"HTTP method","enum":["POST","PUT"],"default":"POST"},"authType":{"type":"string","description":"Authentication type","enum":["no_auth","secret","bearer_token"],"default":"no_auth"},"secret":{"type":"string","description":"Secret for HMAC signature (authType=secret)"},"token":{"type":"string","description":"Bearer token (authType=bearer_token)"},"timeout":{"type":"number","description":"Timeout in milliseconds","default":30000},"retryCount":{"type":"number","description":"Number of retry attempts","default":3}}},"ConsensusConfig":{"type":"object","description":"Consensus configuration for multi-annotator agreement","properties":{"version":{"type":"number","description":"Consensus algorithm version (1 or 2, v2 recommended)","enum":[1,2],"default":2},"threshold":{"type":"number","description":"Minimum agreement score (0-1) required to pass","minimum":0,"maximum":1},"adjudicationMethod":{"type":"string","description":"Method for resolving disagreements","enum":["majority","union","intersection","first"],"default":"majority"},"dynamicConsensus":{"type":"boolean","description":"Add more copies if threshold not met","default":false},"minCopies":{"type":"number","description":"Minimum number of consensus copies","minimum":2,"default":2},"maxCopies":{"type":"number","description":"Maximum number of consensus copies (dynamic consensus)","default":5}}},"Batch":{"type":"object","required":["name"],"properties":{"_id":{"type":"string","description":"Batch ID (auto-generated if not provided)"},"name":{"type":"string","description":"Batch name"}}},"PctConfig":{"type":"object","description":"Configuration specific to Point Cloud Tool (PCT) projects.\nThese settings control how 3D point cloud annotation behaves.\n\nExample:\n```json\n{\n  \"allowOverlapping\": false,\n  \"trackingMultipleSensors\": true,\n  \"segmentationMode\": false\n}\n```\n","properties":{"allowOverlapping":{"type":"boolean","description":"Allow overlapping 3D bounding boxes","default":false},"trackingMultipleSensors":{"type":"boolean","description":"Enable tracking across multiple LiDAR sensors","default":false},"segmentationMode":{"type":"boolean","description":"Enable segmentation mode for point clouds","default":false}}},"ProjectResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/Project"}}}}},"Project":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","enum":["ango","pct","iframe"],"default":"ango"},"owner":{"type":"string","description":"Owner email"},"organization":{"type":"string","description":"Organization ID"},"categorySchema":{"$ref":"#/components/schemas/CategorySchema"},"stages":{"type":"array","items":{"$ref":"#/components/schemas/Stage"}},"assignedTo":{"type":"array","items":{"$ref":"#/components/schemas/Assignee"}},"batches":{"type":"array","items":{"$ref":"#/components/schemas/Batch"}},"queueVersion":{"type":"number"},"assetCount":{"type":"integer"},"benchmarkEnabled":{"type":"boolean"},"benchmarkRatio":{"type":"number"},"instructions":{"type":"string","description":"Instructions URL"},"ocrLanguage":{"type":"string"},"idleTimeout":{"type":"number","description":"Idle timeout in seconds"},"projectPlugins":{"type":"object"},"pluginPresets":{"type":"array","items":{"type":"object"}},"errorCodesEnabled":{"type":"boolean"},"errorSchema":{"type":"object"},"exportStorageId":{"type":"string"},"exportStorageBucket":{"type":"string"},"exportStoragePath":{"type":"string"},"exportStorageEnabled":{"type":"boolean"},"taskSkipEnabled":{"type":"boolean"},"unassignSkippedTask":{"type":"boolean"},"gcSyncEnabled":{"type":"boolean"},"deleted":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"Assignee":{"type":"object","properties":{"assignee":{"type":"string","description":"User email"},"role":{"type":"string","enum":["Manager","Labeler","Reviewer","Lead"]}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"BadRequestError":{"description":"Bad request - validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFoundError":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/project/{projectId}":{"post":{"tags":["Projects"],"summary":"Update Project","description":"Updates project configuration and settings","operationId":"updateProject","parameters":[{"$ref":"#/components/parameters/ProjectIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectUpdateRequest"}}}},"responses":{"200":{"description":"Project updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"$ref":"#/components/responses/BadRequestError"},"404":{"$ref":"#/components/responses/NotFoundError"}}}}}}
````

## Delete Project

> Soft deletes a project by marking it as deleted without permanently removing it from the database

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Projects","description":"Project management endpoints"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"ProjectIdParam":{"name":"projectId","in":"path","required":true,"schema":{"type":"string"},"description":"Project ID"}},"schemas":{"MessageResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"message":{"type":"string"}}}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"NotFoundError":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/project/{projectId}":{"delete":{"tags":["Projects"],"summary":"Delete Project","description":"Soft deletes a project by marking it as deleted without permanently removing it from the database","operationId":"deleteProject","parameters":[{"$ref":"#/components/parameters/ProjectIdParam"}],"responses":{"200":{"description":"Project deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"404":{"$ref":"#/components/responses/NotFoundError"}}}}}}
```

## Update Project Assignees

> Assign or update users assigned to a project with specific roles

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Projects","description":"Project management endpoints"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"ProjectIdParam":{"name":"projectId","in":"path","required":true,"schema":{"type":"string"},"description":"Project ID"}},"schemas":{"AssigneeUpdateRequest":{"type":"object","required":["role","assignees"],"properties":{"role":{"type":"string","enum":["Manager","Labeler","Reviewer","Lead"]},"assignees":{"type":"array","items":{"type":"string"},"description":"Array of user emails"},"roleAssignments":{"type":"object","additionalProperties":{"type":"string","enum":["Manager","Labeler","Reviewer","Lead"]},"description":"Optional map of user email to role override. Example - {\"user1@example.com\":\"Reviewer\"}"}}},"ProjectResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/Project"}}}}},"Project":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","enum":["ango","pct","iframe"],"default":"ango"},"owner":{"type":"string","description":"Owner email"},"organization":{"type":"string","description":"Organization ID"},"categorySchema":{"$ref":"#/components/schemas/CategorySchema"},"stages":{"type":"array","items":{"$ref":"#/components/schemas/Stage"}},"assignedTo":{"type":"array","items":{"$ref":"#/components/schemas/Assignee"}},"batches":{"type":"array","items":{"$ref":"#/components/schemas/Batch"}},"queueVersion":{"type":"number"},"assetCount":{"type":"integer"},"benchmarkEnabled":{"type":"boolean"},"benchmarkRatio":{"type":"number"},"instructions":{"type":"string","description":"Instructions URL"},"ocrLanguage":{"type":"string"},"idleTimeout":{"type":"number","description":"Idle timeout in seconds"},"projectPlugins":{"type":"object"},"pluginPresets":{"type":"array","items":{"type":"object"}},"errorCodesEnabled":{"type":"boolean"},"errorSchema":{"type":"object"},"exportStorageId":{"type":"string"},"exportStorageBucket":{"type":"string"},"exportStoragePath":{"type":"string"},"exportStorageEnabled":{"type":"boolean"},"taskSkipEnabled":{"type":"boolean"},"unassignSkippedTask":{"type":"boolean"},"gcSyncEnabled":{"type":"boolean"},"deleted":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CategorySchema":{"type":"object","description":"Label configuration schema that defines the annotation tools, classifications, and relations for a project.\nThis schema determines what annotation types are available to users and how they can label assets.\n\n**Note:** Schema structure varies between Ango and PCT projects.\n- Ango projects: Use standard annotation tools (bounding-box, polygon, etc.)\n- PCT projects: Use PCT tool type with markingTools array and nested classifications with PCT-specific fields\n","properties":{"tools":{"type":"array","description":"Array of annotation tools (bounding box, polygon, segmentation, etc.)","items":{"$ref":"#/components/schemas/Tool"}},"classifications":{"type":"array","description":"Array of classification questions (radio, checkbox, dropdown, text, etc.)","items":{"$ref":"#/components/schemas/Classification"}},"relations":{"type":"array","description":"Array of relation types that can connect annotations","items":{"$ref":"#/components/schemas/Relation"}}}},"Tool":{"type":"object","description":"Annotation tool configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this tool"},"title":{"type":"string","description":"Display name for the tool"},"tool":{"type":"string","description":"Type of annotation tool","enum":["bounding-box","polygon","polyline","point","rotated-bounding-box","segmentation","brush","medical-brush","ner","pdf","pct","angle"]},"required":{"type":"boolean","description":"Whether this annotation is required","default":false},"color":{"type":"string","description":"Hex color code for this annotation class","pattern":"^#[0-9A-Fa-f]{6}$"},"shortcutKey":{"type":"string","description":"Keyboard shortcut for quick selection"},"classifications":{"type":"array","description":"Nested classifications specific to this tool","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow creating multiple instances of this annotation","default":false},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data (for organizing exported annotations)"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"markingTools":{"type":"array","description":"(PCT only) List of marking tools enabled for this PCT tool.\nAvailable marking tools: polygon, polygon2d, polyline, polyline2d, cuboid, rectangle\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}},"truncate":{"type":"boolean","description":"(PCT only) Enable truncation for this tool","default":false},"presetCuboidDimensions":{"type":"boolean","description":"(PCT only) Enable preset cuboid dimensions","default":false},"cuboidLength":{"type":"string","description":"(PCT only) Preset cuboid length value (stored as string)"},"cuboidWidth":{"type":"string","description":"(PCT only) Preset cuboid width value (stored as string)"},"cuboidHeight":{"type":"string","description":"(PCT only) Preset cuboid height value (stored as string)"},"keypointWithVerticalLine":{"type":"boolean","description":"(PCT only) Enable keypoint with vertical line feature","default":false},"edgeLengthConstraint":{"type":"string","description":"(PCT only) Minimum edge length constraint (stored as string)"},"hasInstance":{"type":"boolean","description":"(PCT only) Enable instance tracking for this tool","default":false}}},"Classification":{"type":"object","description":"Classification question configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this classification"},"title":{"type":"string","description":"Question or label text"},"tool":{"type":"string","description":"Type of classification input (same as 'type')","enum":["radio","checkbox","single-dropdown","multi-dropdown","tree-dropdown","single-tree-dropdown","text","boolean"]},"color":{"type":"string","description":"Hex color code for this classification","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether answering this classification is required","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut key"},"columnField":{"type":"boolean","description":"Whether to show in column view","default":false},"frameSpecific":{"type":"boolean","description":"Whether classification is frame-specific (for videos)","default":false},"showDropdown":{"type":"boolean","description":"Whether to show as dropdown in UI","default":false},"richText":{"type":"boolean","description":"Whether to enable rich text input (for text type)","default":false},"regex":{"type":"string","nullable":true,"description":"Regular expression for text validation (for text type)"},"parentOptionId":{"type":"string","nullable":true,"description":"Parent option ID for nested classifications"},"options":{"type":"array","description":"Available options (not used for text type)","items":{"$ref":"#/components/schemas/ClassificationOption"}},"treeOptions":{"type":"array","description":"Tree-structured options (for tree-dropdown types)","items":{"type":"object"}},"classifications":{"type":"array","description":"Nested child classifications","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow multiple selections","default":false},"parentToolType":{"type":"string","description":"(PCT only) Parent tool type this classification belongs to"},"parentToolId":{"type":"string","description":"(PCT only) Parent tool schemaId this classification is associated with"},"attributeLevel":{"type":"string","description":"(PCT only) Level at which this attribute applies","enum":["Class Level","Instance Level"]},"defaultValue":{"description":"Default value for this classification (type varies based on classification tool type)","oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}]},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"attributeMode":{"type":"string","description":"(PCT only) Attribute mode determining how values persist across frames.\n- Time Varying: Value can change per frame\n- Constant: Single value for entire sequence\n- Sensor Specific: Different values per sensor\n","enum":["Time Varying","Constant","Sensor Specific"]},"associatedMarkingTool":{"type":"array","description":"(PCT only) Marking tools this classification is associated with.\nThis classification will only be available when using these marking tools.\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}}}},"ClassificationOption":{"type":"object","description":"Option for a classification question","required":["schemaId","value"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this option"},"value":{"type":"string","description":"Display text and internal value for this option"},"label":{"type":"string","description":"Alternative display text (deprecated, use 'value')"},"children":{"type":"array","description":"Nested classifications that appear when this option is selected","items":{"$ref":"#/components/schemas/Classification"}}}},"Relation":{"type":"object","description":"Relation type that can connect two annotations.\n\n**Relation Types:**\n- `one-to-one`: Direct connection between two annotations (Ango only)\n- `group`: Groups multiple annotations together (Ango only)\n- `one-to-many`: Parent-child hierarchical relationship (PCT only)\n\n**Note:** PCT projects support additional fields like `parentTool` and `childTools` for one-to-many relations.\n","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this relation"},"title":{"type":"string","description":"Display name for the relation"},"tool":{"type":"string","description":"Type of relation tool:\n- `one-to-one`: Direct 1:1 connection between annotations (Ango only)\n- `group`: Non-directional grouping of multiple annotations (Ango only)\n- `one-to-many`: Hierarchical parent-child relationship (PCT only)\n","enum":["one-to-one","group","one-to-many"]},"color":{"type":"string","description":"Hex color code for this relation","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether this relation must be used in annotations","default":false},"classifications":{"type":"array","description":"Nested classification questions attached to this relation.\nAllows adding metadata or attributes to the relationship itself.\n","default":[]},"multiple":{"type":"boolean","description":"Whether multiple instances of this relation can be created","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut to quickly create this relation"},"parentTool":{"type":"string","description":"(PCT only) For one-to-many relations, specifies the schemaId of the parent tool.\nOnly applicable when `tool: \"one-to-many\"`.\n"},"childTools":{"type":"array","description":"(PCT only) For one-to-many relations, specifies the schemaIds of allowed child tools.\nOnly applicable when `tool: \"one-to-many\"`.\n","items":{"type":"string"}}}},"Stage":{"type":"object","description":"Workflow stage configuration. Different stage types have different properties.\n- Label: Manual annotation stage\n- Review: QA/review stage\n- Logic: Conditional routing stage\n- Plugin: ML model integration stage\n- Webhook: External API callback stage\n- Consensus: Multi-annotator agreement stage\n- Hold: Pause stage\n- Start: Entry point (auto-forwards)\n- Complete: Terminal success stage\n- Archive: Terminal archive stage\n","required":["id","type"],"properties":{"id":{"type":"string","description":"Unique identifier for this stage"},"name":{"type":"string","description":"Display name for this stage"},"type":{"type":"string","description":"Type of stage","enum":["Label","Review","Logic","Plugin","Webhook","Consensus","Hold","Start","Complete","Archive"]},"next":{"type":"array","items":{"type":"string"},"description":"Array of next stage IDs (for Logic stages, order matters)"},"position":{"type":"object","description":"Position in workflow diagram UI","properties":{"x":{"type":"number"},"y":{"type":"number"}}},"assignedTo":{"type":"array","description":"Users assigned to work on this stage (Label/Review stages)","items":{"type":"string"}},"rememberAssignee":{"type":"boolean","description":"Auto-assign to previous stage's user (sticky assignment)","default":false},"logic":{"$ref":"#/components/schemas/LogicConfig","description":"Logic routing configuration (Logic stages only)"},"pluginId":{"type":"string","description":"Plugin ID to execute (Plugin stages only)"},"pluginConfig":{"type":"object","description":"Plugin-specific configuration (Plugin stages only)"},"webhook":{"$ref":"#/components/schemas/WebhookConfig","description":"Webhook configuration (Webhook stages only)"},"consensusConfig":{"$ref":"#/components/schemas/ConsensusConfig","description":"Consensus configuration (Consensus stages only)"},"readOnly":{"type":"boolean","description":"Whether this stage is read-only (users can view but not edit)","default":false},"preventRequeue":{"type":"boolean","description":"Prevent tasks from being requeued to this stage","default":false},"autoForward":{"type":"boolean","description":"Automatically advance to next stage without user action","default":true},"consensusId":{"type":"string","description":"Links stage to a consensus stage (used in consensus workflows)"},"consensusDynamic":{"type":"boolean","description":"Dynamic vs static consensus stage","default":false}}},"LogicConfig":{"type":"object","description":"Logic stage routing configuration. Routes tasks based on conditions.\nConditions are evaluated in order, first match wins.\n","properties":{"type":{"type":"string","description":"Type of logic routing","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Default value (usually empty)"},"conditions":{"type":"array","description":"Array of routing conditions","items":{"$ref":"#/components/schemas/LogicCondition"}}}},"LogicCondition":{"type":"object","description":"Individual routing condition for Logic stages","properties":{"type":{"type":"string","description":"Type of condition","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Condition-specific value","properties":{"tools":{"type":"array","description":"Tool filters (AnnotationType logic)","items":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"},"description":"Annotation filters:\n- exists___<schemaId>: Annotation must exist\n- not-exist___<schemaId>: Annotation must NOT exist\n"}}}},"emails":{"type":"array","description":"User emails (Annotator logic)","items":{"type":"string"}},"sampleRate":{"type":"number","description":"Sample rate 0-1 (RandomSample logic)","minimum":0,"maximum":1},"duration":{"type":"number","description":"Duration in milliseconds (Duration logic)"},"operator":{"type":"string","description":"Comparison operator for Duration","enum":["lt","gt","eq"]},"batches":{"type":"array","description":"Batch names (Batch logic)","items":{"type":"string"}}}},"index":{"type":"number","description":"Index of next stage in parent's next array"}}},"WebhookConfig":{"type":"object","description":"Webhook configuration for external API integration","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Webhook endpoint URL"},"method":{"type":"string","description":"HTTP method","enum":["POST","PUT"],"default":"POST"},"authType":{"type":"string","description":"Authentication type","enum":["no_auth","secret","bearer_token"],"default":"no_auth"},"secret":{"type":"string","description":"Secret for HMAC signature (authType=secret)"},"token":{"type":"string","description":"Bearer token (authType=bearer_token)"},"timeout":{"type":"number","description":"Timeout in milliseconds","default":30000},"retryCount":{"type":"number","description":"Number of retry attempts","default":3}}},"ConsensusConfig":{"type":"object","description":"Consensus configuration for multi-annotator agreement","properties":{"version":{"type":"number","description":"Consensus algorithm version (1 or 2, v2 recommended)","enum":[1,2],"default":2},"threshold":{"type":"number","description":"Minimum agreement score (0-1) required to pass","minimum":0,"maximum":1},"adjudicationMethod":{"type":"string","description":"Method for resolving disagreements","enum":["majority","union","intersection","first"],"default":"majority"},"dynamicConsensus":{"type":"boolean","description":"Add more copies if threshold not met","default":false},"minCopies":{"type":"number","description":"Minimum number of consensus copies","minimum":2,"default":2},"maxCopies":{"type":"number","description":"Maximum number of consensus copies (dynamic consensus)","default":5}}},"Assignee":{"type":"object","properties":{"assignee":{"type":"string","description":"User email"},"role":{"type":"string","enum":["Manager","Labeler","Reviewer","Lead"]}}},"Batch":{"type":"object","required":["name"],"properties":{"_id":{"type":"string","description":"Batch ID (auto-generated if not provided)"},"name":{"type":"string","description":"Batch name"}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"BadRequestError":{"description":"Bad request - validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/project/{projectId}/assigned":{"post":{"tags":["Projects"],"summary":"Update Project Assignees","description":"Assign or update users assigned to a project with specific roles","operationId":"updateAssignees","parameters":[{"$ref":"#/components/parameters/ProjectIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssigneeUpdateRequest"}}}},"responses":{"200":{"description":"Assignees updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"$ref":"#/components/responses/BadRequestError"}}}}}}
```

## Update Project Workflow

> Updates the workflow configuration for a project independently from other project settings.\
> \
> \*\*Important:\*\*\
> \- Validates workflow for circular dependencies\
> \- Creates workflow history entry for auditing\
> \- Does NOT trigger PCT service notification\
> \- Requires complete stages array (Start, Complete, and at least one working stage)\
> \
> \*\*Use Cases:\*\*\
> \- Modify stage connections and routing\
> \- Add/remove workflow stages\
> \- Update stage properties (assignees, logic, webhooks)\
> \- Configure consensus workflows<br>

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Projects","description":"Project management endpoints"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"ProjectIdParam":{"name":"projectId","in":"path","required":true,"schema":{"type":"string"},"description":"Project ID"}},"schemas":{"WorkflowUpdateRequest":{"type":"object","description":"Request body for updating project workflow stages","required":["stages"],"properties":{"stages":{"type":"array","description":"Complete array of workflow stages for the project","items":{"$ref":"#/components/schemas/Stage"},"minItems":3}}},"Stage":{"type":"object","description":"Workflow stage configuration. Different stage types have different properties.\n- Label: Manual annotation stage\n- Review: QA/review stage\n- Logic: Conditional routing stage\n- Plugin: ML model integration stage\n- Webhook: External API callback stage\n- Consensus: Multi-annotator agreement stage\n- Hold: Pause stage\n- Start: Entry point (auto-forwards)\n- Complete: Terminal success stage\n- Archive: Terminal archive stage\n","required":["id","type"],"properties":{"id":{"type":"string","description":"Unique identifier for this stage"},"name":{"type":"string","description":"Display name for this stage"},"type":{"type":"string","description":"Type of stage","enum":["Label","Review","Logic","Plugin","Webhook","Consensus","Hold","Start","Complete","Archive"]},"next":{"type":"array","items":{"type":"string"},"description":"Array of next stage IDs (for Logic stages, order matters)"},"position":{"type":"object","description":"Position in workflow diagram UI","properties":{"x":{"type":"number"},"y":{"type":"number"}}},"assignedTo":{"type":"array","description":"Users assigned to work on this stage (Label/Review stages)","items":{"type":"string"}},"rememberAssignee":{"type":"boolean","description":"Auto-assign to previous stage's user (sticky assignment)","default":false},"logic":{"$ref":"#/components/schemas/LogicConfig","description":"Logic routing configuration (Logic stages only)"},"pluginId":{"type":"string","description":"Plugin ID to execute (Plugin stages only)"},"pluginConfig":{"type":"object","description":"Plugin-specific configuration (Plugin stages only)"},"webhook":{"$ref":"#/components/schemas/WebhookConfig","description":"Webhook configuration (Webhook stages only)"},"consensusConfig":{"$ref":"#/components/schemas/ConsensusConfig","description":"Consensus configuration (Consensus stages only)"},"readOnly":{"type":"boolean","description":"Whether this stage is read-only (users can view but not edit)","default":false},"preventRequeue":{"type":"boolean","description":"Prevent tasks from being requeued to this stage","default":false},"autoForward":{"type":"boolean","description":"Automatically advance to next stage without user action","default":true},"consensusId":{"type":"string","description":"Links stage to a consensus stage (used in consensus workflows)"},"consensusDynamic":{"type":"boolean","description":"Dynamic vs static consensus stage","default":false}}},"LogicConfig":{"type":"object","description":"Logic stage routing configuration. Routes tasks based on conditions.\nConditions are evaluated in order, first match wins.\n","properties":{"type":{"type":"string","description":"Type of logic routing","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Default value (usually empty)"},"conditions":{"type":"array","description":"Array of routing conditions","items":{"$ref":"#/components/schemas/LogicCondition"}}}},"LogicCondition":{"type":"object","description":"Individual routing condition for Logic stages","properties":{"type":{"type":"string","description":"Type of condition","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Condition-specific value","properties":{"tools":{"type":"array","description":"Tool filters (AnnotationType logic)","items":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"},"description":"Annotation filters:\n- exists___<schemaId>: Annotation must exist\n- not-exist___<schemaId>: Annotation must NOT exist\n"}}}},"emails":{"type":"array","description":"User emails (Annotator logic)","items":{"type":"string"}},"sampleRate":{"type":"number","description":"Sample rate 0-1 (RandomSample logic)","minimum":0,"maximum":1},"duration":{"type":"number","description":"Duration in milliseconds (Duration logic)"},"operator":{"type":"string","description":"Comparison operator for Duration","enum":["lt","gt","eq"]},"batches":{"type":"array","description":"Batch names (Batch logic)","items":{"type":"string"}}}},"index":{"type":"number","description":"Index of next stage in parent's next array"}}},"WebhookConfig":{"type":"object","description":"Webhook configuration for external API integration","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Webhook endpoint URL"},"method":{"type":"string","description":"HTTP method","enum":["POST","PUT"],"default":"POST"},"authType":{"type":"string","description":"Authentication type","enum":["no_auth","secret","bearer_token"],"default":"no_auth"},"secret":{"type":"string","description":"Secret for HMAC signature (authType=secret)"},"token":{"type":"string","description":"Bearer token (authType=bearer_token)"},"timeout":{"type":"number","description":"Timeout in milliseconds","default":30000},"retryCount":{"type":"number","description":"Number of retry attempts","default":3}}},"ConsensusConfig":{"type":"object","description":"Consensus configuration for multi-annotator agreement","properties":{"version":{"type":"number","description":"Consensus algorithm version (1 or 2, v2 recommended)","enum":[1,2],"default":2},"threshold":{"type":"number","description":"Minimum agreement score (0-1) required to pass","minimum":0,"maximum":1},"adjudicationMethod":{"type":"string","description":"Method for resolving disagreements","enum":["majority","union","intersection","first"],"default":"majority"},"dynamicConsensus":{"type":"boolean","description":"Add more copies if threshold not met","default":false},"minCopies":{"type":"number","description":"Minimum number of consensus copies","minimum":2,"default":2},"maxCopies":{"type":"number","description":"Maximum number of consensus copies (dynamic consensus)","default":5}}},"ProjectResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/Project"}}}}},"Project":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","enum":["ango","pct","iframe"],"default":"ango"},"owner":{"type":"string","description":"Owner email"},"organization":{"type":"string","description":"Organization ID"},"categorySchema":{"$ref":"#/components/schemas/CategorySchema"},"stages":{"type":"array","items":{"$ref":"#/components/schemas/Stage"}},"assignedTo":{"type":"array","items":{"$ref":"#/components/schemas/Assignee"}},"batches":{"type":"array","items":{"$ref":"#/components/schemas/Batch"}},"queueVersion":{"type":"number"},"assetCount":{"type":"integer"},"benchmarkEnabled":{"type":"boolean"},"benchmarkRatio":{"type":"number"},"instructions":{"type":"string","description":"Instructions URL"},"ocrLanguage":{"type":"string"},"idleTimeout":{"type":"number","description":"Idle timeout in seconds"},"projectPlugins":{"type":"object"},"pluginPresets":{"type":"array","items":{"type":"object"}},"errorCodesEnabled":{"type":"boolean"},"errorSchema":{"type":"object"},"exportStorageId":{"type":"string"},"exportStorageBucket":{"type":"string"},"exportStoragePath":{"type":"string"},"exportStorageEnabled":{"type":"boolean"},"taskSkipEnabled":{"type":"boolean"},"unassignSkippedTask":{"type":"boolean"},"gcSyncEnabled":{"type":"boolean"},"deleted":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CategorySchema":{"type":"object","description":"Label configuration schema that defines the annotation tools, classifications, and relations for a project.\nThis schema determines what annotation types are available to users and how they can label assets.\n\n**Note:** Schema structure varies between Ango and PCT projects.\n- Ango projects: Use standard annotation tools (bounding-box, polygon, etc.)\n- PCT projects: Use PCT tool type with markingTools array and nested classifications with PCT-specific fields\n","properties":{"tools":{"type":"array","description":"Array of annotation tools (bounding box, polygon, segmentation, etc.)","items":{"$ref":"#/components/schemas/Tool"}},"classifications":{"type":"array","description":"Array of classification questions (radio, checkbox, dropdown, text, etc.)","items":{"$ref":"#/components/schemas/Classification"}},"relations":{"type":"array","description":"Array of relation types that can connect annotations","items":{"$ref":"#/components/schemas/Relation"}}}},"Tool":{"type":"object","description":"Annotation tool configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this tool"},"title":{"type":"string","description":"Display name for the tool"},"tool":{"type":"string","description":"Type of annotation tool","enum":["bounding-box","polygon","polyline","point","rotated-bounding-box","segmentation","brush","medical-brush","ner","pdf","pct","angle"]},"required":{"type":"boolean","description":"Whether this annotation is required","default":false},"color":{"type":"string","description":"Hex color code for this annotation class","pattern":"^#[0-9A-Fa-f]{6}$"},"shortcutKey":{"type":"string","description":"Keyboard shortcut for quick selection"},"classifications":{"type":"array","description":"Nested classifications specific to this tool","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow creating multiple instances of this annotation","default":false},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data (for organizing exported annotations)"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"markingTools":{"type":"array","description":"(PCT only) List of marking tools enabled for this PCT tool.\nAvailable marking tools: polygon, polygon2d, polyline, polyline2d, cuboid, rectangle\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}},"truncate":{"type":"boolean","description":"(PCT only) Enable truncation for this tool","default":false},"presetCuboidDimensions":{"type":"boolean","description":"(PCT only) Enable preset cuboid dimensions","default":false},"cuboidLength":{"type":"string","description":"(PCT only) Preset cuboid length value (stored as string)"},"cuboidWidth":{"type":"string","description":"(PCT only) Preset cuboid width value (stored as string)"},"cuboidHeight":{"type":"string","description":"(PCT only) Preset cuboid height value (stored as string)"},"keypointWithVerticalLine":{"type":"boolean","description":"(PCT only) Enable keypoint with vertical line feature","default":false},"edgeLengthConstraint":{"type":"string","description":"(PCT only) Minimum edge length constraint (stored as string)"},"hasInstance":{"type":"boolean","description":"(PCT only) Enable instance tracking for this tool","default":false}}},"Classification":{"type":"object","description":"Classification question configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this classification"},"title":{"type":"string","description":"Question or label text"},"tool":{"type":"string","description":"Type of classification input (same as 'type')","enum":["radio","checkbox","single-dropdown","multi-dropdown","tree-dropdown","single-tree-dropdown","text","boolean"]},"color":{"type":"string","description":"Hex color code for this classification","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether answering this classification is required","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut key"},"columnField":{"type":"boolean","description":"Whether to show in column view","default":false},"frameSpecific":{"type":"boolean","description":"Whether classification is frame-specific (for videos)","default":false},"showDropdown":{"type":"boolean","description":"Whether to show as dropdown in UI","default":false},"richText":{"type":"boolean","description":"Whether to enable rich text input (for text type)","default":false},"regex":{"type":"string","nullable":true,"description":"Regular expression for text validation (for text type)"},"parentOptionId":{"type":"string","nullable":true,"description":"Parent option ID for nested classifications"},"options":{"type":"array","description":"Available options (not used for text type)","items":{"$ref":"#/components/schemas/ClassificationOption"}},"treeOptions":{"type":"array","description":"Tree-structured options (for tree-dropdown types)","items":{"type":"object"}},"classifications":{"type":"array","description":"Nested child classifications","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow multiple selections","default":false},"parentToolType":{"type":"string","description":"(PCT only) Parent tool type this classification belongs to"},"parentToolId":{"type":"string","description":"(PCT only) Parent tool schemaId this classification is associated with"},"attributeLevel":{"type":"string","description":"(PCT only) Level at which this attribute applies","enum":["Class Level","Instance Level"]},"defaultValue":{"description":"Default value for this classification (type varies based on classification tool type)","oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}]},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"attributeMode":{"type":"string","description":"(PCT only) Attribute mode determining how values persist across frames.\n- Time Varying: Value can change per frame\n- Constant: Single value for entire sequence\n- Sensor Specific: Different values per sensor\n","enum":["Time Varying","Constant","Sensor Specific"]},"associatedMarkingTool":{"type":"array","description":"(PCT only) Marking tools this classification is associated with.\nThis classification will only be available when using these marking tools.\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}}}},"ClassificationOption":{"type":"object","description":"Option for a classification question","required":["schemaId","value"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this option"},"value":{"type":"string","description":"Display text and internal value for this option"},"label":{"type":"string","description":"Alternative display text (deprecated, use 'value')"},"children":{"type":"array","description":"Nested classifications that appear when this option is selected","items":{"$ref":"#/components/schemas/Classification"}}}},"Relation":{"type":"object","description":"Relation type that can connect two annotations.\n\n**Relation Types:**\n- `one-to-one`: Direct connection between two annotations (Ango only)\n- `group`: Groups multiple annotations together (Ango only)\n- `one-to-many`: Parent-child hierarchical relationship (PCT only)\n\n**Note:** PCT projects support additional fields like `parentTool` and `childTools` for one-to-many relations.\n","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this relation"},"title":{"type":"string","description":"Display name for the relation"},"tool":{"type":"string","description":"Type of relation tool:\n- `one-to-one`: Direct 1:1 connection between annotations (Ango only)\n- `group`: Non-directional grouping of multiple annotations (Ango only)\n- `one-to-many`: Hierarchical parent-child relationship (PCT only)\n","enum":["one-to-one","group","one-to-many"]},"color":{"type":"string","description":"Hex color code for this relation","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether this relation must be used in annotations","default":false},"classifications":{"type":"array","description":"Nested classification questions attached to this relation.\nAllows adding metadata or attributes to the relationship itself.\n","default":[]},"multiple":{"type":"boolean","description":"Whether multiple instances of this relation can be created","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut to quickly create this relation"},"parentTool":{"type":"string","description":"(PCT only) For one-to-many relations, specifies the schemaId of the parent tool.\nOnly applicable when `tool: \"one-to-many\"`.\n"},"childTools":{"type":"array","description":"(PCT only) For one-to-many relations, specifies the schemaIds of allowed child tools.\nOnly applicable when `tool: \"one-to-many\"`.\n","items":{"type":"string"}}}},"Assignee":{"type":"object","properties":{"assignee":{"type":"string","description":"User email"},"role":{"type":"string","enum":["Manager","Labeler","Reviewer","Lead"]}}},"Batch":{"type":"object","required":["name"],"properties":{"_id":{"type":"string","description":"Batch ID (auto-generated if not provided)"},"name":{"type":"string","description":"Batch name"}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"BadRequestError":{"description":"Bad request - validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFoundError":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/project/{projectId}/workflow":{"post":{"tags":["Projects"],"summary":"Update Project Workflow","description":"Updates the workflow configuration for a project independently from other project settings.\n\n**Important:**\n- Validates workflow for circular dependencies\n- Creates workflow history entry for auditing\n- Does NOT trigger PCT service notification\n- Requires complete stages array (Start, Complete, and at least one working stage)\n\n**Use Cases:**\n- Modify stage connections and routing\n- Add/remove workflow stages\n- Update stage properties (assignees, logic, webhooks)\n- Configure consensus workflows\n","operationId":"updateWorkflow","parameters":[{"$ref":"#/components/parameters/ProjectIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowUpdateRequest"}}}},"responses":{"200":{"description":"Workflow updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"$ref":"#/components/responses/BadRequestError"},"404":{"$ref":"#/components/responses/NotFoundError"}}}}}}
```

## Update Category Schema

> Updates the annotation tools and classification schema for a project independently from other settings.\
> \
> \*\*Important:\*\*\
> \- Creates category schema history entry for auditing\
> \- For PCT projects: Automatically notifies PCT service to sync schema\
> \- Does NOT affect workflow or other project settings\
> \- Schema defines available annotation tools, classifications, and relations\
> \
> \*\*Use Cases:\*\*\
> \- Add/remove annotation tools (bounding box, polygon, segmentation, etc.)\
> \- Modify classification questions and options\
> \- Update tool properties (colors, shortcuts, requirements)\
> \- Configure PCT-specific tools and attributes<br>

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Projects","description":"Project management endpoints"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"ProjectIdParam":{"name":"projectId","in":"path","required":true,"schema":{"type":"string"},"description":"Project ID"}},"schemas":{"CategorySchemaUpdateRequest":{"type":"object","description":"Request body for updating project category schema (annotation tools and classifications)","required":["categorySchema"],"properties":{"categorySchema":{"$ref":"#/components/schemas/CategorySchema"}}},"CategorySchema":{"type":"object","description":"Label configuration schema that defines the annotation tools, classifications, and relations for a project.\nThis schema determines what annotation types are available to users and how they can label assets.\n\n**Note:** Schema structure varies between Ango and PCT projects.\n- Ango projects: Use standard annotation tools (bounding-box, polygon, etc.)\n- PCT projects: Use PCT tool type with markingTools array and nested classifications with PCT-specific fields\n","properties":{"tools":{"type":"array","description":"Array of annotation tools (bounding box, polygon, segmentation, etc.)","items":{"$ref":"#/components/schemas/Tool"}},"classifications":{"type":"array","description":"Array of classification questions (radio, checkbox, dropdown, text, etc.)","items":{"$ref":"#/components/schemas/Classification"}},"relations":{"type":"array","description":"Array of relation types that can connect annotations","items":{"$ref":"#/components/schemas/Relation"}}}},"Tool":{"type":"object","description":"Annotation tool configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this tool"},"title":{"type":"string","description":"Display name for the tool"},"tool":{"type":"string","description":"Type of annotation tool","enum":["bounding-box","polygon","polyline","point","rotated-bounding-box","segmentation","brush","medical-brush","ner","pdf","pct","angle"]},"required":{"type":"boolean","description":"Whether this annotation is required","default":false},"color":{"type":"string","description":"Hex color code for this annotation class","pattern":"^#[0-9A-Fa-f]{6}$"},"shortcutKey":{"type":"string","description":"Keyboard shortcut for quick selection"},"classifications":{"type":"array","description":"Nested classifications specific to this tool","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow creating multiple instances of this annotation","default":false},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data (for organizing exported annotations)"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"markingTools":{"type":"array","description":"(PCT only) List of marking tools enabled for this PCT tool.\nAvailable marking tools: polygon, polygon2d, polyline, polyline2d, cuboid, rectangle\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}},"truncate":{"type":"boolean","description":"(PCT only) Enable truncation for this tool","default":false},"presetCuboidDimensions":{"type":"boolean","description":"(PCT only) Enable preset cuboid dimensions","default":false},"cuboidLength":{"type":"string","description":"(PCT only) Preset cuboid length value (stored as string)"},"cuboidWidth":{"type":"string","description":"(PCT only) Preset cuboid width value (stored as string)"},"cuboidHeight":{"type":"string","description":"(PCT only) Preset cuboid height value (stored as string)"},"keypointWithVerticalLine":{"type":"boolean","description":"(PCT only) Enable keypoint with vertical line feature","default":false},"edgeLengthConstraint":{"type":"string","description":"(PCT only) Minimum edge length constraint (stored as string)"},"hasInstance":{"type":"boolean","description":"(PCT only) Enable instance tracking for this tool","default":false}}},"Classification":{"type":"object","description":"Classification question configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this classification"},"title":{"type":"string","description":"Question or label text"},"tool":{"type":"string","description":"Type of classification input (same as 'type')","enum":["radio","checkbox","single-dropdown","multi-dropdown","tree-dropdown","single-tree-dropdown","text","boolean"]},"color":{"type":"string","description":"Hex color code for this classification","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether answering this classification is required","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut key"},"columnField":{"type":"boolean","description":"Whether to show in column view","default":false},"frameSpecific":{"type":"boolean","description":"Whether classification is frame-specific (for videos)","default":false},"showDropdown":{"type":"boolean","description":"Whether to show as dropdown in UI","default":false},"richText":{"type":"boolean","description":"Whether to enable rich text input (for text type)","default":false},"regex":{"type":"string","nullable":true,"description":"Regular expression for text validation (for text type)"},"parentOptionId":{"type":"string","nullable":true,"description":"Parent option ID for nested classifications"},"options":{"type":"array","description":"Available options (not used for text type)","items":{"$ref":"#/components/schemas/ClassificationOption"}},"treeOptions":{"type":"array","description":"Tree-structured options (for tree-dropdown types)","items":{"type":"object"}},"classifications":{"type":"array","description":"Nested child classifications","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow multiple selections","default":false},"parentToolType":{"type":"string","description":"(PCT only) Parent tool type this classification belongs to"},"parentToolId":{"type":"string","description":"(PCT only) Parent tool schemaId this classification is associated with"},"attributeLevel":{"type":"string","description":"(PCT only) Level at which this attribute applies","enum":["Class Level","Instance Level"]},"defaultValue":{"description":"Default value for this classification (type varies based on classification tool type)","oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}]},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"attributeMode":{"type":"string","description":"(PCT only) Attribute mode determining how values persist across frames.\n- Time Varying: Value can change per frame\n- Constant: Single value for entire sequence\n- Sensor Specific: Different values per sensor\n","enum":["Time Varying","Constant","Sensor Specific"]},"associatedMarkingTool":{"type":"array","description":"(PCT only) Marking tools this classification is associated with.\nThis classification will only be available when using these marking tools.\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}}}},"ClassificationOption":{"type":"object","description":"Option for a classification question","required":["schemaId","value"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this option"},"value":{"type":"string","description":"Display text and internal value for this option"},"label":{"type":"string","description":"Alternative display text (deprecated, use 'value')"},"children":{"type":"array","description":"Nested classifications that appear when this option is selected","items":{"$ref":"#/components/schemas/Classification"}}}},"Relation":{"type":"object","description":"Relation type that can connect two annotations.\n\n**Relation Types:**\n- `one-to-one`: Direct connection between two annotations (Ango only)\n- `group`: Groups multiple annotations together (Ango only)\n- `one-to-many`: Parent-child hierarchical relationship (PCT only)\n\n**Note:** PCT projects support additional fields like `parentTool` and `childTools` for one-to-many relations.\n","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this relation"},"title":{"type":"string","description":"Display name for the relation"},"tool":{"type":"string","description":"Type of relation tool:\n- `one-to-one`: Direct 1:1 connection between annotations (Ango only)\n- `group`: Non-directional grouping of multiple annotations (Ango only)\n- `one-to-many`: Hierarchical parent-child relationship (PCT only)\n","enum":["one-to-one","group","one-to-many"]},"color":{"type":"string","description":"Hex color code for this relation","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether this relation must be used in annotations","default":false},"classifications":{"type":"array","description":"Nested classification questions attached to this relation.\nAllows adding metadata or attributes to the relationship itself.\n","default":[]},"multiple":{"type":"boolean","description":"Whether multiple instances of this relation can be created","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut to quickly create this relation"},"parentTool":{"type":"string","description":"(PCT only) For one-to-many relations, specifies the schemaId of the parent tool.\nOnly applicable when `tool: \"one-to-many\"`.\n"},"childTools":{"type":"array","description":"(PCT only) For one-to-many relations, specifies the schemaIds of allowed child tools.\nOnly applicable when `tool: \"one-to-many\"`.\n","items":{"type":"string"}}}},"ProjectResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/Project"}}}}},"Project":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","enum":["ango","pct","iframe"],"default":"ango"},"owner":{"type":"string","description":"Owner email"},"organization":{"type":"string","description":"Organization ID"},"categorySchema":{"$ref":"#/components/schemas/CategorySchema"},"stages":{"type":"array","items":{"$ref":"#/components/schemas/Stage"}},"assignedTo":{"type":"array","items":{"$ref":"#/components/schemas/Assignee"}},"batches":{"type":"array","items":{"$ref":"#/components/schemas/Batch"}},"queueVersion":{"type":"number"},"assetCount":{"type":"integer"},"benchmarkEnabled":{"type":"boolean"},"benchmarkRatio":{"type":"number"},"instructions":{"type":"string","description":"Instructions URL"},"ocrLanguage":{"type":"string"},"idleTimeout":{"type":"number","description":"Idle timeout in seconds"},"projectPlugins":{"type":"object"},"pluginPresets":{"type":"array","items":{"type":"object"}},"errorCodesEnabled":{"type":"boolean"},"errorSchema":{"type":"object"},"exportStorageId":{"type":"string"},"exportStorageBucket":{"type":"string"},"exportStoragePath":{"type":"string"},"exportStorageEnabled":{"type":"boolean"},"taskSkipEnabled":{"type":"boolean"},"unassignSkippedTask":{"type":"boolean"},"gcSyncEnabled":{"type":"boolean"},"deleted":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"Stage":{"type":"object","description":"Workflow stage configuration. Different stage types have different properties.\n- Label: Manual annotation stage\n- Review: QA/review stage\n- Logic: Conditional routing stage\n- Plugin: ML model integration stage\n- Webhook: External API callback stage\n- Consensus: Multi-annotator agreement stage\n- Hold: Pause stage\n- Start: Entry point (auto-forwards)\n- Complete: Terminal success stage\n- Archive: Terminal archive stage\n","required":["id","type"],"properties":{"id":{"type":"string","description":"Unique identifier for this stage"},"name":{"type":"string","description":"Display name for this stage"},"type":{"type":"string","description":"Type of stage","enum":["Label","Review","Logic","Plugin","Webhook","Consensus","Hold","Start","Complete","Archive"]},"next":{"type":"array","items":{"type":"string"},"description":"Array of next stage IDs (for Logic stages, order matters)"},"position":{"type":"object","description":"Position in workflow diagram UI","properties":{"x":{"type":"number"},"y":{"type":"number"}}},"assignedTo":{"type":"array","description":"Users assigned to work on this stage (Label/Review stages)","items":{"type":"string"}},"rememberAssignee":{"type":"boolean","description":"Auto-assign to previous stage's user (sticky assignment)","default":false},"logic":{"$ref":"#/components/schemas/LogicConfig","description":"Logic routing configuration (Logic stages only)"},"pluginId":{"type":"string","description":"Plugin ID to execute (Plugin stages only)"},"pluginConfig":{"type":"object","description":"Plugin-specific configuration (Plugin stages only)"},"webhook":{"$ref":"#/components/schemas/WebhookConfig","description":"Webhook configuration (Webhook stages only)"},"consensusConfig":{"$ref":"#/components/schemas/ConsensusConfig","description":"Consensus configuration (Consensus stages only)"},"readOnly":{"type":"boolean","description":"Whether this stage is read-only (users can view but not edit)","default":false},"preventRequeue":{"type":"boolean","description":"Prevent tasks from being requeued to this stage","default":false},"autoForward":{"type":"boolean","description":"Automatically advance to next stage without user action","default":true},"consensusId":{"type":"string","description":"Links stage to a consensus stage (used in consensus workflows)"},"consensusDynamic":{"type":"boolean","description":"Dynamic vs static consensus stage","default":false}}},"LogicConfig":{"type":"object","description":"Logic stage routing configuration. Routes tasks based on conditions.\nConditions are evaluated in order, first match wins.\n","properties":{"type":{"type":"string","description":"Type of logic routing","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Default value (usually empty)"},"conditions":{"type":"array","description":"Array of routing conditions","items":{"$ref":"#/components/schemas/LogicCondition"}}}},"LogicCondition":{"type":"object","description":"Individual routing condition for Logic stages","properties":{"type":{"type":"string","description":"Type of condition","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Condition-specific value","properties":{"tools":{"type":"array","description":"Tool filters (AnnotationType logic)","items":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"},"description":"Annotation filters:\n- exists___<schemaId>: Annotation must exist\n- not-exist___<schemaId>: Annotation must NOT exist\n"}}}},"emails":{"type":"array","description":"User emails (Annotator logic)","items":{"type":"string"}},"sampleRate":{"type":"number","description":"Sample rate 0-1 (RandomSample logic)","minimum":0,"maximum":1},"duration":{"type":"number","description":"Duration in milliseconds (Duration logic)"},"operator":{"type":"string","description":"Comparison operator for Duration","enum":["lt","gt","eq"]},"batches":{"type":"array","description":"Batch names (Batch logic)","items":{"type":"string"}}}},"index":{"type":"number","description":"Index of next stage in parent's next array"}}},"WebhookConfig":{"type":"object","description":"Webhook configuration for external API integration","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Webhook endpoint URL"},"method":{"type":"string","description":"HTTP method","enum":["POST","PUT"],"default":"POST"},"authType":{"type":"string","description":"Authentication type","enum":["no_auth","secret","bearer_token"],"default":"no_auth"},"secret":{"type":"string","description":"Secret for HMAC signature (authType=secret)"},"token":{"type":"string","description":"Bearer token (authType=bearer_token)"},"timeout":{"type":"number","description":"Timeout in milliseconds","default":30000},"retryCount":{"type":"number","description":"Number of retry attempts","default":3}}},"ConsensusConfig":{"type":"object","description":"Consensus configuration for multi-annotator agreement","properties":{"version":{"type":"number","description":"Consensus algorithm version (1 or 2, v2 recommended)","enum":[1,2],"default":2},"threshold":{"type":"number","description":"Minimum agreement score (0-1) required to pass","minimum":0,"maximum":1},"adjudicationMethod":{"type":"string","description":"Method for resolving disagreements","enum":["majority","union","intersection","first"],"default":"majority"},"dynamicConsensus":{"type":"boolean","description":"Add more copies if threshold not met","default":false},"minCopies":{"type":"number","description":"Minimum number of consensus copies","minimum":2,"default":2},"maxCopies":{"type":"number","description":"Maximum number of consensus copies (dynamic consensus)","default":5}}},"Assignee":{"type":"object","properties":{"assignee":{"type":"string","description":"User email"},"role":{"type":"string","enum":["Manager","Labeler","Reviewer","Lead"]}}},"Batch":{"type":"object","required":["name"],"properties":{"_id":{"type":"string","description":"Batch ID (auto-generated if not provided)"},"name":{"type":"string","description":"Batch name"}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"BadRequestError":{"description":"Bad request - validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFoundError":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/project/{projectId}/categorySchema":{"post":{"tags":["Projects"],"summary":"Update Category Schema","description":"Updates the annotation tools and classification schema for a project independently from other settings.\n\n**Important:**\n- Creates category schema history entry for auditing\n- For PCT projects: Automatically notifies PCT service to sync schema\n- Does NOT affect workflow or other project settings\n- Schema defines available annotation tools, classifications, and relations\n\n**Use Cases:**\n- Add/remove annotation tools (bounding box, polygon, segmentation, etc.)\n- Modify classification questions and options\n- Update tool properties (colors, shortcuts, requirements)\n- Configure PCT-specific tools and attributes\n","operationId":"updateCategorySchema","parameters":[{"$ref":"#/components/parameters/ProjectIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategorySchemaUpdateRequest"}}}},"responses":{"200":{"description":"Category schema updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"$ref":"#/components/responses/BadRequestError"},"404":{"$ref":"#/components/responses/NotFoundError"}}}}}}
```

## Update Label Validation

> Updates the label validation configuration for a project independently from other settings.\
> \
> \*\*Important:\*\*\
> \- Allows custom JavaScript/Python validation functions to check annotation quality\
> \- For PCT projects: Automatically sends validation function to PCT service\
> \- Supports both custom validation functions and external validation APIs\
> \- Validation can optionally prevent task submission\
> \
> \*\*Custom Validation Function:\*\*\
> \- JavaScript for Ango projects\
> \- Python for PCT projects\
> \- Function receives \`answers\` object containing annotation data\
> \- Must return array of error objects with: \`objectId\`, \`message\`, \`preventSubmission\`\
> \
> \*\*External Validation:\*\*\
> \- Call external API to validate annotations\
> \- Useful for ML-based quality checks or custom business logic\
> \- Configure frame-specific validation for video projects\
> \
> \*\*Use Cases:\*\*\
> \- Enforce minimum bounding box sizes\
> \- Validate annotation completeness\
> \- Check for required attributes\
> \- Integrate with external quality systems<br>

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Projects","description":"Project management endpoints"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"ProjectIdParam":{"name":"projectId","in":"path","required":true,"schema":{"type":"string"},"description":"Project ID"}},"schemas":{"LabelValidationUpdateRequest":{"type":"object","description":"Request body for updating project label validation configuration.\nSupports custom validation functions (JavaScript for Ango, Python for PCT) and external API validation.\n","properties":{"validationFunction":{"type":"string","description":"Custom validation function as a string.\n- For Ango projects: JavaScript function that receives `answers` object\n- For PCT projects: Python function that receives `answers` dict\n- Must return array/list of error objects with: objectId, message, preventSubmission\n"},"customValidationEnabled":{"type":"boolean","description":"Enable/disable custom validation function execution"},"submissionPrevent":{"type":"boolean","description":"Globally prevent task submission when validation fails (optional)"},"externalValidation":{"$ref":"#/components/schemas/ExternalValidation"}}},"ExternalValidation":{"type":"object","description":"Configuration for external API-based validation","properties":{"enabled":{"type":"boolean","description":"Enable external validation API calls","default":false},"apiUrl":{"type":"string","description":"URL of external validation API endpoint","default":""},"singleFrame":{"type":"boolean","description":"For video projects - validate only a single frame","default":false},"specificFrame":{"type":"boolean","description":"For video projects - validate specific frame(s)","default":false},"frameNumbers":{"type":"string","description":"Frame number(s) to validate for video projects","default":""}}},"ProjectResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/Project"}}}}},"Project":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","enum":["ango","pct","iframe"],"default":"ango"},"owner":{"type":"string","description":"Owner email"},"organization":{"type":"string","description":"Organization ID"},"categorySchema":{"$ref":"#/components/schemas/CategorySchema"},"stages":{"type":"array","items":{"$ref":"#/components/schemas/Stage"}},"assignedTo":{"type":"array","items":{"$ref":"#/components/schemas/Assignee"}},"batches":{"type":"array","items":{"$ref":"#/components/schemas/Batch"}},"queueVersion":{"type":"number"},"assetCount":{"type":"integer"},"benchmarkEnabled":{"type":"boolean"},"benchmarkRatio":{"type":"number"},"instructions":{"type":"string","description":"Instructions URL"},"ocrLanguage":{"type":"string"},"idleTimeout":{"type":"number","description":"Idle timeout in seconds"},"projectPlugins":{"type":"object"},"pluginPresets":{"type":"array","items":{"type":"object"}},"errorCodesEnabled":{"type":"boolean"},"errorSchema":{"type":"object"},"exportStorageId":{"type":"string"},"exportStorageBucket":{"type":"string"},"exportStoragePath":{"type":"string"},"exportStorageEnabled":{"type":"boolean"},"taskSkipEnabled":{"type":"boolean"},"unassignSkippedTask":{"type":"boolean"},"gcSyncEnabled":{"type":"boolean"},"deleted":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CategorySchema":{"type":"object","description":"Label configuration schema that defines the annotation tools, classifications, and relations for a project.\nThis schema determines what annotation types are available to users and how they can label assets.\n\n**Note:** Schema structure varies between Ango and PCT projects.\n- Ango projects: Use standard annotation tools (bounding-box, polygon, etc.)\n- PCT projects: Use PCT tool type with markingTools array and nested classifications with PCT-specific fields\n","properties":{"tools":{"type":"array","description":"Array of annotation tools (bounding box, polygon, segmentation, etc.)","items":{"$ref":"#/components/schemas/Tool"}},"classifications":{"type":"array","description":"Array of classification questions (radio, checkbox, dropdown, text, etc.)","items":{"$ref":"#/components/schemas/Classification"}},"relations":{"type":"array","description":"Array of relation types that can connect annotations","items":{"$ref":"#/components/schemas/Relation"}}}},"Tool":{"type":"object","description":"Annotation tool configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this tool"},"title":{"type":"string","description":"Display name for the tool"},"tool":{"type":"string","description":"Type of annotation tool","enum":["bounding-box","polygon","polyline","point","rotated-bounding-box","segmentation","brush","medical-brush","ner","pdf","pct","angle"]},"required":{"type":"boolean","description":"Whether this annotation is required","default":false},"color":{"type":"string","description":"Hex color code for this annotation class","pattern":"^#[0-9A-Fa-f]{6}$"},"shortcutKey":{"type":"string","description":"Keyboard shortcut for quick selection"},"classifications":{"type":"array","description":"Nested classifications specific to this tool","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow creating multiple instances of this annotation","default":false},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data (for organizing exported annotations)"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"markingTools":{"type":"array","description":"(PCT only) List of marking tools enabled for this PCT tool.\nAvailable marking tools: polygon, polygon2d, polyline, polyline2d, cuboid, rectangle\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}},"truncate":{"type":"boolean","description":"(PCT only) Enable truncation for this tool","default":false},"presetCuboidDimensions":{"type":"boolean","description":"(PCT only) Enable preset cuboid dimensions","default":false},"cuboidLength":{"type":"string","description":"(PCT only) Preset cuboid length value (stored as string)"},"cuboidWidth":{"type":"string","description":"(PCT only) Preset cuboid width value (stored as string)"},"cuboidHeight":{"type":"string","description":"(PCT only) Preset cuboid height value (stored as string)"},"keypointWithVerticalLine":{"type":"boolean","description":"(PCT only) Enable keypoint with vertical line feature","default":false},"edgeLengthConstraint":{"type":"string","description":"(PCT only) Minimum edge length constraint (stored as string)"},"hasInstance":{"type":"boolean","description":"(PCT only) Enable instance tracking for this tool","default":false}}},"Classification":{"type":"object","description":"Classification question configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this classification"},"title":{"type":"string","description":"Question or label text"},"tool":{"type":"string","description":"Type of classification input (same as 'type')","enum":["radio","checkbox","single-dropdown","multi-dropdown","tree-dropdown","single-tree-dropdown","text","boolean"]},"color":{"type":"string","description":"Hex color code for this classification","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether answering this classification is required","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut key"},"columnField":{"type":"boolean","description":"Whether to show in column view","default":false},"frameSpecific":{"type":"boolean","description":"Whether classification is frame-specific (for videos)","default":false},"showDropdown":{"type":"boolean","description":"Whether to show as dropdown in UI","default":false},"richText":{"type":"boolean","description":"Whether to enable rich text input (for text type)","default":false},"regex":{"type":"string","nullable":true,"description":"Regular expression for text validation (for text type)"},"parentOptionId":{"type":"string","nullable":true,"description":"Parent option ID for nested classifications"},"options":{"type":"array","description":"Available options (not used for text type)","items":{"$ref":"#/components/schemas/ClassificationOption"}},"treeOptions":{"type":"array","description":"Tree-structured options (for tree-dropdown types)","items":{"type":"object"}},"classifications":{"type":"array","description":"Nested child classifications","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow multiple selections","default":false},"parentToolType":{"type":"string","description":"(PCT only) Parent tool type this classification belongs to"},"parentToolId":{"type":"string","description":"(PCT only) Parent tool schemaId this classification is associated with"},"attributeLevel":{"type":"string","description":"(PCT only) Level at which this attribute applies","enum":["Class Level","Instance Level"]},"defaultValue":{"description":"Default value for this classification (type varies based on classification tool type)","oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}]},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"attributeMode":{"type":"string","description":"(PCT only) Attribute mode determining how values persist across frames.\n- Time Varying: Value can change per frame\n- Constant: Single value for entire sequence\n- Sensor Specific: Different values per sensor\n","enum":["Time Varying","Constant","Sensor Specific"]},"associatedMarkingTool":{"type":"array","description":"(PCT only) Marking tools this classification is associated with.\nThis classification will only be available when using these marking tools.\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}}}},"ClassificationOption":{"type":"object","description":"Option for a classification question","required":["schemaId","value"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this option"},"value":{"type":"string","description":"Display text and internal value for this option"},"label":{"type":"string","description":"Alternative display text (deprecated, use 'value')"},"children":{"type":"array","description":"Nested classifications that appear when this option is selected","items":{"$ref":"#/components/schemas/Classification"}}}},"Relation":{"type":"object","description":"Relation type that can connect two annotations.\n\n**Relation Types:**\n- `one-to-one`: Direct connection between two annotations (Ango only)\n- `group`: Groups multiple annotations together (Ango only)\n- `one-to-many`: Parent-child hierarchical relationship (PCT only)\n\n**Note:** PCT projects support additional fields like `parentTool` and `childTools` for one-to-many relations.\n","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this relation"},"title":{"type":"string","description":"Display name for the relation"},"tool":{"type":"string","description":"Type of relation tool:\n- `one-to-one`: Direct 1:1 connection between annotations (Ango only)\n- `group`: Non-directional grouping of multiple annotations (Ango only)\n- `one-to-many`: Hierarchical parent-child relationship (PCT only)\n","enum":["one-to-one","group","one-to-many"]},"color":{"type":"string","description":"Hex color code for this relation","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether this relation must be used in annotations","default":false},"classifications":{"type":"array","description":"Nested classification questions attached to this relation.\nAllows adding metadata or attributes to the relationship itself.\n","default":[]},"multiple":{"type":"boolean","description":"Whether multiple instances of this relation can be created","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut to quickly create this relation"},"parentTool":{"type":"string","description":"(PCT only) For one-to-many relations, specifies the schemaId of the parent tool.\nOnly applicable when `tool: \"one-to-many\"`.\n"},"childTools":{"type":"array","description":"(PCT only) For one-to-many relations, specifies the schemaIds of allowed child tools.\nOnly applicable when `tool: \"one-to-many\"`.\n","items":{"type":"string"}}}},"Stage":{"type":"object","description":"Workflow stage configuration. Different stage types have different properties.\n- Label: Manual annotation stage\n- Review: QA/review stage\n- Logic: Conditional routing stage\n- Plugin: ML model integration stage\n- Webhook: External API callback stage\n- Consensus: Multi-annotator agreement stage\n- Hold: Pause stage\n- Start: Entry point (auto-forwards)\n- Complete: Terminal success stage\n- Archive: Terminal archive stage\n","required":["id","type"],"properties":{"id":{"type":"string","description":"Unique identifier for this stage"},"name":{"type":"string","description":"Display name for this stage"},"type":{"type":"string","description":"Type of stage","enum":["Label","Review","Logic","Plugin","Webhook","Consensus","Hold","Start","Complete","Archive"]},"next":{"type":"array","items":{"type":"string"},"description":"Array of next stage IDs (for Logic stages, order matters)"},"position":{"type":"object","description":"Position in workflow diagram UI","properties":{"x":{"type":"number"},"y":{"type":"number"}}},"assignedTo":{"type":"array","description":"Users assigned to work on this stage (Label/Review stages)","items":{"type":"string"}},"rememberAssignee":{"type":"boolean","description":"Auto-assign to previous stage's user (sticky assignment)","default":false},"logic":{"$ref":"#/components/schemas/LogicConfig","description":"Logic routing configuration (Logic stages only)"},"pluginId":{"type":"string","description":"Plugin ID to execute (Plugin stages only)"},"pluginConfig":{"type":"object","description":"Plugin-specific configuration (Plugin stages only)"},"webhook":{"$ref":"#/components/schemas/WebhookConfig","description":"Webhook configuration (Webhook stages only)"},"consensusConfig":{"$ref":"#/components/schemas/ConsensusConfig","description":"Consensus configuration (Consensus stages only)"},"readOnly":{"type":"boolean","description":"Whether this stage is read-only (users can view but not edit)","default":false},"preventRequeue":{"type":"boolean","description":"Prevent tasks from being requeued to this stage","default":false},"autoForward":{"type":"boolean","description":"Automatically advance to next stage without user action","default":true},"consensusId":{"type":"string","description":"Links stage to a consensus stage (used in consensus workflows)"},"consensusDynamic":{"type":"boolean","description":"Dynamic vs static consensus stage","default":false}}},"LogicConfig":{"type":"object","description":"Logic stage routing configuration. Routes tasks based on conditions.\nConditions are evaluated in order, first match wins.\n","properties":{"type":{"type":"string","description":"Type of logic routing","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Default value (usually empty)"},"conditions":{"type":"array","description":"Array of routing conditions","items":{"$ref":"#/components/schemas/LogicCondition"}}}},"LogicCondition":{"type":"object","description":"Individual routing condition for Logic stages","properties":{"type":{"type":"string","description":"Type of condition","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Condition-specific value","properties":{"tools":{"type":"array","description":"Tool filters (AnnotationType logic)","items":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"},"description":"Annotation filters:\n- exists___<schemaId>: Annotation must exist\n- not-exist___<schemaId>: Annotation must NOT exist\n"}}}},"emails":{"type":"array","description":"User emails (Annotator logic)","items":{"type":"string"}},"sampleRate":{"type":"number","description":"Sample rate 0-1 (RandomSample logic)","minimum":0,"maximum":1},"duration":{"type":"number","description":"Duration in milliseconds (Duration logic)"},"operator":{"type":"string","description":"Comparison operator for Duration","enum":["lt","gt","eq"]},"batches":{"type":"array","description":"Batch names (Batch logic)","items":{"type":"string"}}}},"index":{"type":"number","description":"Index of next stage in parent's next array"}}},"WebhookConfig":{"type":"object","description":"Webhook configuration for external API integration","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Webhook endpoint URL"},"method":{"type":"string","description":"HTTP method","enum":["POST","PUT"],"default":"POST"},"authType":{"type":"string","description":"Authentication type","enum":["no_auth","secret","bearer_token"],"default":"no_auth"},"secret":{"type":"string","description":"Secret for HMAC signature (authType=secret)"},"token":{"type":"string","description":"Bearer token (authType=bearer_token)"},"timeout":{"type":"number","description":"Timeout in milliseconds","default":30000},"retryCount":{"type":"number","description":"Number of retry attempts","default":3}}},"ConsensusConfig":{"type":"object","description":"Consensus configuration for multi-annotator agreement","properties":{"version":{"type":"number","description":"Consensus algorithm version (1 or 2, v2 recommended)","enum":[1,2],"default":2},"threshold":{"type":"number","description":"Minimum agreement score (0-1) required to pass","minimum":0,"maximum":1},"adjudicationMethod":{"type":"string","description":"Method for resolving disagreements","enum":["majority","union","intersection","first"],"default":"majority"},"dynamicConsensus":{"type":"boolean","description":"Add more copies if threshold not met","default":false},"minCopies":{"type":"number","description":"Minimum number of consensus copies","minimum":2,"default":2},"maxCopies":{"type":"number","description":"Maximum number of consensus copies (dynamic consensus)","default":5}}},"Assignee":{"type":"object","properties":{"assignee":{"type":"string","description":"User email"},"role":{"type":"string","enum":["Manager","Labeler","Reviewer","Lead"]}}},"Batch":{"type":"object","required":["name"],"properties":{"_id":{"type":"string","description":"Batch ID (auto-generated if not provided)"},"name":{"type":"string","description":"Batch name"}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"BadRequestError":{"description":"Bad request - validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFoundError":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/project/{projectId}/labelValidation":{"post":{"tags":["Projects"],"summary":"Update Label Validation","description":"Updates the label validation configuration for a project independently from other settings.\n\n**Important:**\n- Allows custom JavaScript/Python validation functions to check annotation quality\n- For PCT projects: Automatically sends validation function to PCT service\n- Supports both custom validation functions and external validation APIs\n- Validation can optionally prevent task submission\n\n**Custom Validation Function:**\n- JavaScript for Ango projects\n- Python for PCT projects\n- Function receives `answers` object containing annotation data\n- Must return array of error objects with: `objectId`, `message`, `preventSubmission`\n\n**External Validation:**\n- Call external API to validate annotations\n- Useful for ML-based quality checks or custom business logic\n- Configure frame-specific validation for video projects\n\n**Use Cases:**\n- Enforce minimum bounding box sizes\n- Validate annotation completeness\n- Check for required attributes\n- Integrate with external quality systems\n","operationId":"updateLabelValidation","parameters":[{"$ref":"#/components/parameters/ProjectIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelValidationUpdateRequest"}}}},"responses":{"200":{"description":"Label validation updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"$ref":"#/components/responses/BadRequestError"},"404":{"$ref":"#/components/responses/NotFoundError"}}}}}}
```

## Create Asset Builder Template

> Creates a template for asset builder functionality

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Projects","description":"Project management endpoints"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"ProjectIdParam":{"name":"projectId","in":"path","required":true,"schema":{"type":"string"},"description":"Project ID"}},"schemas":{"AssetBuilderTemplateRequest":{"type":"object","required":["name","config"],"properties":{"name":{"type":"string"},"config":{"type":"object"}}},"AssetBuilderTemplateResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"template":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"config":{"type":"object"}}}}}}}}},"paths":{"/project/{projectId}/assetBuilderTemplates":{"post":{"tags":["Projects"],"summary":"Create Asset Builder Template","description":"Creates a template for asset builder functionality","operationId":"createAssetBuilderTemplate","parameters":[{"$ref":"#/components/parameters/ProjectIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetBuilderTemplateRequest"}}}},"responses":{"200":{"description":"Template created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetBuilderTemplateResponse"}}}}}}}}}
```

## Upload Project Instructions

> Uploads instruction file for a project (PDF format only)

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Projects","description":"Project management endpoints"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"ProjectIdParam":{"name":"projectId","in":"path","required":true,"schema":{"type":"string"},"description":"Project ID"}},"schemas":{"ProjectResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/Project"}}}}},"Project":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","enum":["ango","pct","iframe"],"default":"ango"},"owner":{"type":"string","description":"Owner email"},"organization":{"type":"string","description":"Organization ID"},"categorySchema":{"$ref":"#/components/schemas/CategorySchema"},"stages":{"type":"array","items":{"$ref":"#/components/schemas/Stage"}},"assignedTo":{"type":"array","items":{"$ref":"#/components/schemas/Assignee"}},"batches":{"type":"array","items":{"$ref":"#/components/schemas/Batch"}},"queueVersion":{"type":"number"},"assetCount":{"type":"integer"},"benchmarkEnabled":{"type":"boolean"},"benchmarkRatio":{"type":"number"},"instructions":{"type":"string","description":"Instructions URL"},"ocrLanguage":{"type":"string"},"idleTimeout":{"type":"number","description":"Idle timeout in seconds"},"projectPlugins":{"type":"object"},"pluginPresets":{"type":"array","items":{"type":"object"}},"errorCodesEnabled":{"type":"boolean"},"errorSchema":{"type":"object"},"exportStorageId":{"type":"string"},"exportStorageBucket":{"type":"string"},"exportStoragePath":{"type":"string"},"exportStorageEnabled":{"type":"boolean"},"taskSkipEnabled":{"type":"boolean"},"unassignSkippedTask":{"type":"boolean"},"gcSyncEnabled":{"type":"boolean"},"deleted":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CategorySchema":{"type":"object","description":"Label configuration schema that defines the annotation tools, classifications, and relations for a project.\nThis schema determines what annotation types are available to users and how they can label assets.\n\n**Note:** Schema structure varies between Ango and PCT projects.\n- Ango projects: Use standard annotation tools (bounding-box, polygon, etc.)\n- PCT projects: Use PCT tool type with markingTools array and nested classifications with PCT-specific fields\n","properties":{"tools":{"type":"array","description":"Array of annotation tools (bounding box, polygon, segmentation, etc.)","items":{"$ref":"#/components/schemas/Tool"}},"classifications":{"type":"array","description":"Array of classification questions (radio, checkbox, dropdown, text, etc.)","items":{"$ref":"#/components/schemas/Classification"}},"relations":{"type":"array","description":"Array of relation types that can connect annotations","items":{"$ref":"#/components/schemas/Relation"}}}},"Tool":{"type":"object","description":"Annotation tool configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this tool"},"title":{"type":"string","description":"Display name for the tool"},"tool":{"type":"string","description":"Type of annotation tool","enum":["bounding-box","polygon","polyline","point","rotated-bounding-box","segmentation","brush","medical-brush","ner","pdf","pct","angle"]},"required":{"type":"boolean","description":"Whether this annotation is required","default":false},"color":{"type":"string","description":"Hex color code for this annotation class","pattern":"^#[0-9A-Fa-f]{6}$"},"shortcutKey":{"type":"string","description":"Keyboard shortcut for quick selection"},"classifications":{"type":"array","description":"Nested classifications specific to this tool","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow creating multiple instances of this annotation","default":false},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data (for organizing exported annotations)"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"markingTools":{"type":"array","description":"(PCT only) List of marking tools enabled for this PCT tool.\nAvailable marking tools: polygon, polygon2d, polyline, polyline2d, cuboid, rectangle\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}},"truncate":{"type":"boolean","description":"(PCT only) Enable truncation for this tool","default":false},"presetCuboidDimensions":{"type":"boolean","description":"(PCT only) Enable preset cuboid dimensions","default":false},"cuboidLength":{"type":"string","description":"(PCT only) Preset cuboid length value (stored as string)"},"cuboidWidth":{"type":"string","description":"(PCT only) Preset cuboid width value (stored as string)"},"cuboidHeight":{"type":"string","description":"(PCT only) Preset cuboid height value (stored as string)"},"keypointWithVerticalLine":{"type":"boolean","description":"(PCT only) Enable keypoint with vertical line feature","default":false},"edgeLengthConstraint":{"type":"string","description":"(PCT only) Minimum edge length constraint (stored as string)"},"hasInstance":{"type":"boolean","description":"(PCT only) Enable instance tracking for this tool","default":false}}},"Classification":{"type":"object","description":"Classification question configuration","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this classification"},"title":{"type":"string","description":"Question or label text"},"tool":{"type":"string","description":"Type of classification input (same as 'type')","enum":["radio","checkbox","single-dropdown","multi-dropdown","tree-dropdown","single-tree-dropdown","text","boolean"]},"color":{"type":"string","description":"Hex color code for this classification","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether answering this classification is required","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut key"},"columnField":{"type":"boolean","description":"Whether to show in column view","default":false},"frameSpecific":{"type":"boolean","description":"Whether classification is frame-specific (for videos)","default":false},"showDropdown":{"type":"boolean","description":"Whether to show as dropdown in UI","default":false},"richText":{"type":"boolean","description":"Whether to enable rich text input (for text type)","default":false},"regex":{"type":"string","nullable":true,"description":"Regular expression for text validation (for text type)"},"parentOptionId":{"type":"string","nullable":true,"description":"Parent option ID for nested classifications"},"options":{"type":"array","description":"Available options (not used for text type)","items":{"$ref":"#/components/schemas/ClassificationOption"}},"treeOptions":{"type":"array","description":"Tree-structured options (for tree-dropdown types)","items":{"type":"object"}},"classifications":{"type":"array","description":"Nested child classifications","items":{"$ref":"#/components/schemas/Classification"}},"multiple":{"type":"boolean","description":"Allow multiple selections","default":false},"parentToolType":{"type":"string","description":"(PCT only) Parent tool type this classification belongs to"},"parentToolId":{"type":"string","description":"(PCT only) Parent tool schemaId this classification is associated with"},"attributeLevel":{"type":"string","description":"(PCT only) Level at which this attribute applies","enum":["Class Level","Instance Level"]},"defaultValue":{"description":"Default value for this classification (type varies based on classification tool type)","oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}]},"exportName":{"type":"string","description":"(PCT only) Name used when exporting data"},"displayName":{"type":"string","description":"(PCT only) Display name shown in the annotation interface"},"abbreviatedName":{"type":"string","description":"(PCT only) Abbreviated name for compact UI views"},"attributeMode":{"type":"string","description":"(PCT only) Attribute mode determining how values persist across frames.\n- Time Varying: Value can change per frame\n- Constant: Single value for entire sequence\n- Sensor Specific: Different values per sensor\n","enum":["Time Varying","Constant","Sensor Specific"]},"associatedMarkingTool":{"type":"array","description":"(PCT only) Marking tools this classification is associated with.\nThis classification will only be available when using these marking tools.\n","items":{"type":"string","enum":["polygon","polygon2d","polyline","polyline2d","cuboid","rectangle"]}}}},"ClassificationOption":{"type":"object","description":"Option for a classification question","required":["schemaId","value"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this option"},"value":{"type":"string","description":"Display text and internal value for this option"},"label":{"type":"string","description":"Alternative display text (deprecated, use 'value')"},"children":{"type":"array","description":"Nested classifications that appear when this option is selected","items":{"$ref":"#/components/schemas/Classification"}}}},"Relation":{"type":"object","description":"Relation type that can connect two annotations.\n\n**Relation Types:**\n- `one-to-one`: Direct connection between two annotations (Ango only)\n- `group`: Groups multiple annotations together (Ango only)\n- `one-to-many`: Parent-child hierarchical relationship (PCT only)\n\n**Note:** PCT projects support additional fields like `parentTool` and `childTools` for one-to-many relations.\n","required":["schemaId","title","tool"],"properties":{"schemaId":{"type":"string","description":"Unique identifier for this relation"},"title":{"type":"string","description":"Display name for the relation"},"tool":{"type":"string","description":"Type of relation tool:\n- `one-to-one`: Direct 1:1 connection between annotations (Ango only)\n- `group`: Non-directional grouping of multiple annotations (Ango only)\n- `one-to-many`: Hierarchical parent-child relationship (PCT only)\n","enum":["one-to-one","group","one-to-many"]},"color":{"type":"string","description":"Hex color code for this relation","pattern":"^#[0-9A-Fa-f]{6}$"},"required":{"type":"boolean","description":"Whether this relation must be used in annotations","default":false},"classifications":{"type":"array","description":"Nested classification questions attached to this relation.\nAllows adding metadata or attributes to the relationship itself.\n","default":[]},"multiple":{"type":"boolean","description":"Whether multiple instances of this relation can be created","default":false},"shortcutKey":{"type":"string","description":"Keyboard shortcut to quickly create this relation"},"parentTool":{"type":"string","description":"(PCT only) For one-to-many relations, specifies the schemaId of the parent tool.\nOnly applicable when `tool: \"one-to-many\"`.\n"},"childTools":{"type":"array","description":"(PCT only) For one-to-many relations, specifies the schemaIds of allowed child tools.\nOnly applicable when `tool: \"one-to-many\"`.\n","items":{"type":"string"}}}},"Stage":{"type":"object","description":"Workflow stage configuration. Different stage types have different properties.\n- Label: Manual annotation stage\n- Review: QA/review stage\n- Logic: Conditional routing stage\n- Plugin: ML model integration stage\n- Webhook: External API callback stage\n- Consensus: Multi-annotator agreement stage\n- Hold: Pause stage\n- Start: Entry point (auto-forwards)\n- Complete: Terminal success stage\n- Archive: Terminal archive stage\n","required":["id","type"],"properties":{"id":{"type":"string","description":"Unique identifier for this stage"},"name":{"type":"string","description":"Display name for this stage"},"type":{"type":"string","description":"Type of stage","enum":["Label","Review","Logic","Plugin","Webhook","Consensus","Hold","Start","Complete","Archive"]},"next":{"type":"array","items":{"type":"string"},"description":"Array of next stage IDs (for Logic stages, order matters)"},"position":{"type":"object","description":"Position in workflow diagram UI","properties":{"x":{"type":"number"},"y":{"type":"number"}}},"assignedTo":{"type":"array","description":"Users assigned to work on this stage (Label/Review stages)","items":{"type":"string"}},"rememberAssignee":{"type":"boolean","description":"Auto-assign to previous stage's user (sticky assignment)","default":false},"logic":{"$ref":"#/components/schemas/LogicConfig","description":"Logic routing configuration (Logic stages only)"},"pluginId":{"type":"string","description":"Plugin ID to execute (Plugin stages only)"},"pluginConfig":{"type":"object","description":"Plugin-specific configuration (Plugin stages only)"},"webhook":{"$ref":"#/components/schemas/WebhookConfig","description":"Webhook configuration (Webhook stages only)"},"consensusConfig":{"$ref":"#/components/schemas/ConsensusConfig","description":"Consensus configuration (Consensus stages only)"},"readOnly":{"type":"boolean","description":"Whether this stage is read-only (users can view but not edit)","default":false},"preventRequeue":{"type":"boolean","description":"Prevent tasks from being requeued to this stage","default":false},"autoForward":{"type":"boolean","description":"Automatically advance to next stage without user action","default":true},"consensusId":{"type":"string","description":"Links stage to a consensus stage (used in consensus workflows)"},"consensusDynamic":{"type":"boolean","description":"Dynamic vs static consensus stage","default":false}}},"LogicConfig":{"type":"object","description":"Logic stage routing configuration. Routes tasks based on conditions.\nConditions are evaluated in order, first match wins.\n","properties":{"type":{"type":"string","description":"Type of logic routing","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Default value (usually empty)"},"conditions":{"type":"array","description":"Array of routing conditions","items":{"$ref":"#/components/schemas/LogicCondition"}}}},"LogicCondition":{"type":"object","description":"Individual routing condition for Logic stages","properties":{"type":{"type":"string","description":"Type of condition","enum":["AnnotationType","Annotator","RandomSample","Duration","Batch","IssueErrorCode"]},"value":{"type":"object","description":"Condition-specific value","properties":{"tools":{"type":"array","description":"Tool filters (AnnotationType logic)","items":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"},"description":"Annotation filters:\n- exists___<schemaId>: Annotation must exist\n- not-exist___<schemaId>: Annotation must NOT exist\n"}}}},"emails":{"type":"array","description":"User emails (Annotator logic)","items":{"type":"string"}},"sampleRate":{"type":"number","description":"Sample rate 0-1 (RandomSample logic)","minimum":0,"maximum":1},"duration":{"type":"number","description":"Duration in milliseconds (Duration logic)"},"operator":{"type":"string","description":"Comparison operator for Duration","enum":["lt","gt","eq"]},"batches":{"type":"array","description":"Batch names (Batch logic)","items":{"type":"string"}}}},"index":{"type":"number","description":"Index of next stage in parent's next array"}}},"WebhookConfig":{"type":"object","description":"Webhook configuration for external API integration","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Webhook endpoint URL"},"method":{"type":"string","description":"HTTP method","enum":["POST","PUT"],"default":"POST"},"authType":{"type":"string","description":"Authentication type","enum":["no_auth","secret","bearer_token"],"default":"no_auth"},"secret":{"type":"string","description":"Secret for HMAC signature (authType=secret)"},"token":{"type":"string","description":"Bearer token (authType=bearer_token)"},"timeout":{"type":"number","description":"Timeout in milliseconds","default":30000},"retryCount":{"type":"number","description":"Number of retry attempts","default":3}}},"ConsensusConfig":{"type":"object","description":"Consensus configuration for multi-annotator agreement","properties":{"version":{"type":"number","description":"Consensus algorithm version (1 or 2, v2 recommended)","enum":[1,2],"default":2},"threshold":{"type":"number","description":"Minimum agreement score (0-1) required to pass","minimum":0,"maximum":1},"adjudicationMethod":{"type":"string","description":"Method for resolving disagreements","enum":["majority","union","intersection","first"],"default":"majority"},"dynamicConsensus":{"type":"boolean","description":"Add more copies if threshold not met","default":false},"minCopies":{"type":"number","description":"Minimum number of consensus copies","minimum":2,"default":2},"maxCopies":{"type":"number","description":"Maximum number of consensus copies (dynamic consensus)","default":5}}},"Assignee":{"type":"object","properties":{"assignee":{"type":"string","description":"User email"},"role":{"type":"string","enum":["Manager","Labeler","Reviewer","Lead"]}}},"Batch":{"type":"object","required":["name"],"properties":{"_id":{"type":"string","description":"Batch ID (auto-generated if not provided)"},"name":{"type":"string","description":"Batch name"}}}}},"paths":{"/project/{projectId}/instructions":{"post":{"tags":["Projects"],"summary":"Upload Project Instructions","description":"Uploads instruction file for a project (PDF format only)","operationId":"uploadInstructions","parameters":[{"$ref":"#/components/parameters/ProjectIdParam"},{"name":"storageId","in":"query","schema":{"type":"string"},"description":"Custom storage ID"},{"name":"bucket","in":"query","schema":{"type":"string"},"description":"Custom bucket name"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"Instruction file to upload"}},"required":["file"]}}}},"responses":{"200":{"description":"Instructions uploaded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}}}}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.imerit.net/api/docs/projects.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
