IssuesApi

class IssuesApi(api)[source]

Bases: ModuleApiBase

API for working with annotation issues and comments.

Parameters:
api

Api object to use for API connection.

Usage Example:
import supervisely as sly
api = sly.Api.from_env()
issues = api.issues.get_list(team_id=1)

Methods

add

Add a new issue and return information about it.

add_comment

Add a comment to the issue with the specified ID.

add_subissue

Add a subissue to the specified issue.

convert_info_to_json

Convert information about an entity to a dictionary.

get_info_by_id

Get information about the issue by its ID.

get_list

Get list of issues in the specified team.

get_list_all_pages

Get list of all or limited quantity entities from the Supervisely server.

get_list_all_pages_generator

This generator function retrieves a list of all or a limited quantity of entities from the Supervisely server, yielding batches of entities as they are retrieved

get_list_by_dataset

Get all issues bound to entities within the specified dataset or project, including sub-issues and the raw bindings that link each sub-issue to its image or labeled object.

get_list_idx_page_async

Get the list of items for a given page number.

get_list_page_generator_async

Yields list of images in dataset asynchronously page by page.

info_sequence

Sequence of fields that are returned by the API to represent IssueInfo.

info_tuple_name

Name of the tuple that represents IssueInfo.

remove

Remove the issue by its ID.

resolve_binding_image_id

Resolve the image ID a get_list_by_dataset() record is bound to, if any.

update

Update information about the issue.

update_comment

Update the comment with the specified ID.

update_subissue

Update a sub-issue, e.g. to close it or move it under a different parent issue.

Attributes

MAX_WAIT_ATTEMPTS

Maximum number of attempts that will be made to wait for a certain condition to be met.

WAIT_ATTEMPT_TIMEOUT_SEC

Number of seconds for intervals between attempts.

InfoType

alias of IssueInfo

classmethod convert_info_to_json(info)

Convert information about an entity to a dictionary.

Parameters:
info : NamedTuple

Information about the entity.

Returns:

Dictionary with information about the entity.

Return type:

dict

static info_sequence()[source]

Sequence of fields that are returned by the API to represent IssueInfo.

static info_tuple_name()[source]

Name of the tuple that represents IssueInfo.

static resolve_binding_image_id(record)[source]

Resolve the image ID a get_list_by_dataset() record is bound to, if any.

Parameters:
record : dict

One record from get_list_by_dataset().

Returns:

The image ID, or None if the record is a top-level issue container (no bindings), or its binding isn’t tied to a single image (projectId/jobId).

Return type:

int, optional

add(team_id, issue_name, comment=None, assignees=None, is_local=False)[source]

Add a new issue and return information about it.

Parameters:
team_id : int

Team ID.

issue_name : str

Name of the issue.

comment : str, optional

Comment for the issue.

assignees : List[int], optional

List of user IDs to assign the issue.

is_local : bool

The local issue will be available only for the members of the team, where it was created. If set to False, the issue will be available for all users from all teams.

Returns:

Information about the added issue.

Return type:

IssueInfo

Usage Example:
import os
from dotenv import load_dotenv

import supervisely as sly

# Load secrets and create API object from .env file (recommended)
# Learn more here: https://developer.supervisely.com/getting-started/basics-of-authentication
if sly.is_development():
    load_dotenv(os.path.expanduser("~/supervisely.env"))

api = sly.Api.from_env()

# Add new issue.
new_issue = api.issues.add(team_id=1, issue_name="New issue", comment="Some comment")
add_comment(issue_id, comment)[source]

Add a comment to the issue with the specified ID.

Parameters:
issue_id : int

Issue ID.

comment : str

Comment text.

Returns:

Information about the added comment.

Return type:

CommentInfo

Usage Example:
import os
from dotenv import load_dotenv

import supervisely as sly

# Load secrets and create API object from .env file (recommended)
# Learn more here: https://developer.supervisely.com/getting-started/basics-of-authentication
if sly.is_development():
    load_dotenv(os.path.expanduser("~/supervisely.env"))

api = sly.Api.from_env()

# Add a comment to the issue with the specified ID.
comment_info = api.issues.add_comment(issue_id=1, comment="Some comment")
add_subissue(issue_id, image_ids, label_ids, top, left, annotation_info, project_meta)[source]

Add a subissue to the specified issue. Image and label IDs should be the same type, e.g. both int or list of ints. If they are lists, they should have the same length. Annotation info should be an instance of AnnotationInfo, not Annotation, since the second one does not contain required information.

Parameters:
issue_id : int

Issue ID.

image_ids : Union[int, List[int]]

Image ID or list of image IDs to be binded with the issue.

label_ids : Union[int, List[int]]

Label ID or list of label IDs to be binded with the issue.

top : Union[int, float]

Top position of the marker of subissue in the Labeling interface.

left : Union[int, float]

Left position of the marker of subissue in the Labeling interface.

annotation_info

Information about the annotation.

project_meta

Project meta information.

Returns:

None

Return type:

None

Usage Example:
import os
from dotenv import load_dotenv

import supervisely as sly

# Load secrets and create API object from .env file (recommended)
# Learn more here: https://developer.supervisely.com/getting-started/basics-of-authentication
if sly.is_development():
    load_dotenv(os.path.expanduser("~/supervisely.env"))

api = sly.Api.from_env()

project_id = 123
image_id = 456
label_id = 789

# Get project meta and annotation info.
project_meta = sly.ProjectMeta.from_json(api.project.get_meta(project_id))
annotation_info = api.annotation.download(image_id)

# Add a subissue to the specified issue.
api.issues.add_subissue(
    issue_id=1,
    image_ids=image_id,
    label_ids=label_id,
    top=100,
    left=100,
    annotation_info=annotation_info,
    project_meta=project_meta
)
get_info_by_id(id, with_sub_issues=False)[source]

Get information about the issue by its ID.

NOTE: with_sub_issues=True only resolves the image for a sub-issue that was raised against a specific labeled object (bound to a figureId) — that sub-issue’s imageId will be populated. A sub-issue raised against a whole image (bound directly to an imageId) is not resolved by this method: it comes back with imageId set to None and no way to recover the image from here. To reliably resolve the image for both cases in bulk, use get_list_by_dataset() instead.

Parameters:
id : int

Issue ID.

with_sub_issues : bool, optional

Whether to include the issue’s sub-issues in the response.

Returns:

Information about the issue.

Return type:

IssueInfo

Usage Example:
import os
from dotenv import load_dotenv

import supervisely as sly

# Load secrets and create API object from .env file (recommended)
# Learn more here: https://developer.supervisely.com/getting-started/basics-of-authentication
if sly.is_development():
    load_dotenv(os.path.expanduser("~/supervisely.env"))

api = sly.Api.from_env()

# Get information about the issue by its ID.
issue_info = api.issues.get_info_by_id(1)

# Get information about the issue together with its sub-issues.
issue_info = api.issues.get_info_by_id(1, with_sub_issues=True)
get_list(team_id, filters=None, with_sub_issues=False)[source]

Get list of issues in the specified team.

NOTE on with_sub_issues: has the same partial-resolution behavior as get_info_by_id()’s with_sub_issues — imageId is only resolved for a sub-issue bound to a specific labeled object (figureId); a sub-issue bound directly to a whole image (imageId) still comes back with imageId: None. Use get_list_by_dataset() if you need that case resolved too.

Parameters:
team_id : int

Team ID.

filters : List[Dict[str, str]], optional

List of filters to apply to the list of issues.

with_sub_issues : bool, optional

Whether to include each issue’s sub-issues in the response.

Returns:

List of issues.

Return type:

List[IssueInfo]

Usage Example:
import os
from dotenv import load_dotenv

import supervisely as sly

# Load secrets and create API object from .env file (recommended)
# Learn more here: https://developer.supervisely.com/getting-started/basics-of-authentication
if sly.is_development():
    load_dotenv(os.path.expanduser("~/supervisely.env"))

api = sly.Api.from_env()

# Get list of issues in specified team.
issues = api.issues.get_list(team_id=1)

# Get list of issues together with their sub-issues.
issues = api.issues.get_list(team_id=1, with_sub_issues=True)
get_list_all_pages(method, data, progress_cb=None, convert_json_info_cb=None, limit=None, return_first_response=False)

Get list of all or limited quantity entities from the Supervisely server.

Parameters:
method : str

Request method name

data : dict

Dictionary with request body info

progress_cb : Progress, optional

Function for tracking download progress.

convert_json_info_cb : Callable, optional

Function for convert json info

limit : int, optional

Number of entity to retrieve

return_first_response : bool, optional

Specify if return first response

Returns:

List of entities.

Return type:

List[dict]

get_list_all_pages_generator(method, data, progress_cb=None, convert_json_info_cb=None, limit=None, return_first_response=False)

This generator function retrieves a list of all or a limited quantity of entities from the Supervisely server, yielding batches of entities as they are retrieved

Parameters:
method : str

Request method name

data : dict

Dictionary with request body info

progress_cb : Progress, optional

Function for tracking download progress.

convert_json_info_cb : Callable, optional

Function for convert json info

limit : int, optional

Number of entity to retrieve

return_first_response : bool, optional

Specify if return first response

get_list_by_dataset(dataset_id=None, project_id=None)[source]

Get all issues bound to entities within the specified dataset or project, including sub-issues and the raw bindings that link each sub-issue to its image or labeled object.

Unlike get_list(), which only returns top-level issue containers (never linked to an image), this method is the reliable way to resolve which image (or object) an issue is actually about. Use resolve_binding_image_id() to read the image ID off each record instead of parsing bindings by hand.

NOTE: this endpoint has no per-issue filter and isn’t paginated — it always returns every issue and sub-issue in the given dataset/project in one response. Resolving a single issue’s image this way costs a full dataset/project-wide fetch; there’s no cheaper supported call today for that single-issue case.

The returned list mixes two kinds of records:

  • Top-level issue containers (no bindings key) — not bound to any single entity.

  • Sub-issues (have a bindings key with exactly one entry: {"field": ..., "value": ..., "extra": {...}}). field is one of "imageId", "figureId", "projectId", "jobId". To resolve the image:

    • field == "imageId": the image ID is bindings[0]["value"].

    • field == "figureId": the bound object’s (figure’s) ID is bindings[0]["value"], and its image ID is bindings[0]["extra"]["figureImageId"].

    • field in ("projectId", "jobId"): not tied to a single image.

Parameters:
dataset_id : int, optional

Dataset ID. Exactly one of dataset_id/project_id is required.

project_id : int, optional

Project ID. Exactly one of dataset_id/project_id is required.

Raises:

ValueError – if neither or both of dataset_id/project_id are given.

Returns:

Raw list of issue and sub-issue records, as described above.

Return type:

List[dict]

Usage Example:
import os
from dotenv import load_dotenv

import supervisely as sly

# Load secrets and create API object from .env file (recommended)
# Learn more here: https://developer.supervisely.com/getting-started/basics-of-authentication
if sly.is_development():
    load_dotenv(os.path.expanduser("~/supervisely.env"))

api = sly.Api.from_env()

records = api.issues.get_list_by_dataset(dataset_id=123)

# Count issues per image.
issues_per_image = {}
for record in records:
    image_id = api.issues.resolve_binding_image_id(record)
    if image_id is not None:
        issues_per_image[image_id] = issues_per_image.get(image_id, 0) + 1
async get_list_idx_page_async(method, data)

Get the list of items for a given page number. Page number is specified in the data dictionary.

Parameters:
method : str

Method to call for listing items.

data : dict

Data to pass to the API method.

Returns:

List of items.

Return type:

Tuple[int, List[NamedTuple]]

async get_list_page_generator_async(method, data, pages_count=None, semaphore=None)

Yields list of images in dataset asynchronously page by page.

Parameters:
method : str

Method to call for listing items.

data : dict

Data to pass to the API method.

pages_count : int, optional

Preferred number of pages to retrieve if used with a per_page limit. Will be automatically adjusted if the pagesCount differs from the requested number.

semaphore=None

Semaphore for limiting the number of simultaneous requests.

Returns:

List of images in dataset.

Return type:

AsyncGenerator[List[ImageInfo]]

Usage Example:
import os
from dotenv import load_dotenv

import supervisely as sly

# Load secrets and create API object from .env file (recommended)
# Learn more here: https://developer.supervisely.com/getting-started/basics-of-authentication
if sly.is_development():
    load_dotenv(os.path.expanduser("~/supervisely.env"))

api = sly.Api.from_env()

method = 'images.list'
data = {'datasetId': 123456}

loop = sly.utils.get_or_create_event_loop()
images = loop.run_until_complete(api.image.get_list_generator_async(method, data))
remove(issue_id)[source]

Remove the issue by its ID. NOTE: This operation is irreversible.

Parameters:
issue_id : int

Issue ID.

Usage Example:
import os
from dotenv import load_dotenv

import supervisely as sly

# Load secrets and create API object from .env file (recommended)
# Learn more here: https://developer.supervisely.com/getting-started/basics-of-authentication
if sly.is_development():
    load_dotenv(os.path.expanduser("~/supervisely.env"))

api = sly.Api.from_env()

# Remove the issue by its ID.
api.issues.remove(issue_id=1)
update(issue_id, issue_name=None, status=None, is_pinned=None)[source]

Update information about the issue.

Parameters:
issue_id : int

Issue ID.

issue_name : str, optional

New name of the issue.

status : str, optional

New status of the issue.

is_pinned : bool, optional

Whether the issue is pinned.

Raises:

ValueError – if the status is incorrect. Expected one of [“open”, “closed”], got {status}

Returns:

Information about the issue.

Return type:

IssueInfo

Usage Example:
import os
from dotenv import load_dotenv

import supervisely as sly

# Load secrets and create API object from .env file (recommended)
# Learn more here: https://developer.supervisely.com/getting-started/basics-of-authentication
if sly.is_development():
    load_dotenv(os.path.expanduser("~/supervisely.env"))

api = sly.Api.from_env()

# Update information about the issue.
updated_issue = api.issues.update(issue_id=1, issue_name="Updated issue name")
update_comment(comment_id, comment)[source]

Update the comment with the specified ID.

Parameters:
comment_id : int

Comment ID.

comment : str

New comment text.

Returns:

Information about the updated comment.

Return type:

CommentInfo

Usage Example:
import os
from dotenv import load_dotenv

import supervisely as sly

# Load secrets and create API object from .env file (recommended)
# Learn more here: https://developer.supervisely.com/getting-started/basics-of-authentication
if sly.is_development():
    load_dotenv(os.path.expanduser("~/supervisely.env"))

api = sly.Api.from_env()

# Update the comment with the specified ID.
api.issues.update_comment(comment_id=1, comment="Updated comment")
update_subissue(sub_issue_id, status=None, parent_id=None, meta=None)[source]

Update a sub-issue, e.g. to close it or move it under a different parent issue.

NOTE: unlike update() (for top-level issues), this returns None rather than the updated record — there is no issues.sub-issue.info endpoint to re-fetch a single sub-issue by id, so this mirrors add_subissue(), which has the same limitation.

Parameters:
sub_issue_id : int

Sub-issue ID.

status : str, optional

New status of the sub-issue.

parent_id : int, optional

ID of the issue to move the sub-issue under.

meta : dict, optional

New meta information for the sub-issue (e.g. marker position).

Raises:

ValueError – if the status is incorrect. Expected one of [“open”, “closed”], got {status}

Returns:

None

Return type:

None

Usage Example:
import os
from dotenv import load_dotenv

import supervisely as sly

# Load secrets and create API object from .env file (recommended)
# Learn more here: https://developer.supervisely.com/getting-started/basics-of-authentication
if sly.is_development():
    load_dotenv(os.path.expanduser("~/supervisely.env"))

api = sly.Api.from_env()

# Close a sub-issue.
api.issues.update_subissue(sub_issue_id=1, status="closed")