# 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"}}}}}}}}}
```
