Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,4 @@ debug_*
htmlcov
htmlcov
/CLAUDE.md
.env.example
17 changes: 17 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,23 @@ History

All release highlights of this project will be documented in this file.

4.6.1 - Sep 13, 2026
____________________


**Added**

- ``SAORGClient`` New client for using an Organization API Key to perform organization-level operations across teams.

- ``SAORGClient.list_teams()`` Returns the teams in an organization.

- ``SAORGClient.get_team_client(team_id)`` Returns a SAClient instance for the specified team.

### Updated

- ``SAClient()`` Added support for authentication with Organization API Keys by providing a `team_id`.


4.6.0 - Aug 16, 2026
____________________

Expand Down
8 changes: 8 additions & 0 deletions docs/source/api_reference/api_org_client.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
=====================
SAORGClient interface
=====================

.. _ref_org_client:

.. automethod:: superannotate.SAORGClient.get_team_client
.. automethod:: superannotate.SAORGClient.list_teams
1 change: 1 addition & 0 deletions docs/source/api_reference/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ Contents
:maxdepth: 2

api_client
api_org_client
api_metadata
helpers
55 changes: 53 additions & 2 deletions docs/source/userguide/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,14 @@ on the team setup page, for more details please visit our documentation at https

- **Team API key** — scoped to one team. Works with ``SAClient``.
- **Personal (team-user) API key** — scoped to one team, tied to your user. Works with ``SAClient``.
- **Organization API key** — not scoped to a team. Not supported by the SDK;
``SAClient`` will reject it.
- **Organization API key** — not scoped to a team, so the team to operate in must be supplied alongside it:

.. code-block:: python

SAClient(token="<Organization API key>", team_id=<team_id>)

Instead of passing ``team_id``, you can set ``SA_TEAM_ID`` as an environment variable or in your config file. An explicit ``team_id`` argument takes precedence. Omitting the team entirely raises ``AppException``.
To work across several teams, or when the team isn't known in advance, use ``SAORGClient`` instead — see below.


SAClient can be used with or without arguments
Expand Down Expand Up @@ -76,6 +82,13 @@ ______________________________________________

sa_client = SAClient(token="<API key>")

An Organization API key carries no team, so it is passed together with the team to
operate in:

.. code-block:: python

sa_client = SAClient(token="<Organization API key>", team_id=<team id>)


*Method 2:* Create a custom config file:

Expand All @@ -93,9 +106,12 @@ Custom config.ini example:

[DEFAULT]
SA_TOKEN = <API key>
; Only an Organization API key needs it; other keys carry their own team.
SA_TEAM_ID = <team id>
LOGGING_LEVEL = INFO
LOGGING_PATH = /Users/username/data/superannotate_logs


----------


Expand Down Expand Up @@ -177,3 +193,38 @@ A team contributor can be invited to the team with:
.. code-block:: python

sa_client.invite_contributors_to_team(emails=["admin@superannotate.com"], admin=False)


----------


SAORGClient: organization-scoped access
========================================

``SAORGClient`` authorizes the SDK at the organization level rather than within a single team. Use it when a script operates across several teams, or when the team isn't known in advance.

.. code-block:: python

from superannotate import SAORGClient


org_client = SAORGClient(token="<Organization API key>")
# List the teams in the organization
org_client.list_teams()

# Get a team-scoped client for one of them
sa_client = org_client.get_team_client(team_id=12345)
sa_client.list_projects()

``get_team_client(team_id)`` returns a standard ``SAClient`` bound to that team. It supports the full team-level SDK surface, and no Team API key is created.
As with ``SAClient``, if no ``token`` argument is given, ``SAORGClient`` reads ``SA_TOKEN`` from the environment or from your config file.

**Important notes:**

- ``SAORGClient`` requires an Organization API key. Passing a Team or Personal API
key raises ``AppException``.
- The team is fixed when ``get_team_client()`` is called. To work in a different
team, call ``get_team_client()`` again with the other ID.

For the full list of organization-level methods, see the
:ref:`full method reference <ref_org_client>`.
2 changes: 1 addition & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ minversion = 3.7
log_cli=true
python_files = test_*.py
;pytest_plugins = ['pytest_profiling']
addopts = -n 6 --dist loadscope
;addopts = -n 8 --dist loadscope
6 changes: 5 additions & 1 deletion src/superannotate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
import sys

__version__ = "4.6.0"
__version__ = "4.6.1"


os.environ.update({"sa_version": __version__})
Expand All @@ -15,10 +15,12 @@
from lib.core import PACKAGE_VERSION_INFO_MESSAGE
from lib.core import PACKAGE_VERSION_MAJOR_UPGRADE
from lib.core.exceptions import AppException
from lib.core.exceptions import SAAuthError
from lib.core.exceptions import FileChangedError
from superannotate.lib.app.input_converters import export_annotation
from superannotate.lib.app.input_converters import import_annotation
from superannotate.lib.app.interface.sdk_interface import SAClient
from superannotate.lib.app.interface.sdk_interface import SAORGClient
from superannotate.lib.app.interface.sdk_interface import ItemContext

SESSIONS = {}
Expand All @@ -27,10 +29,12 @@
__all__ = [
"__version__",
"SAClient",
"SAORGClient",
"ItemContext",
# Utils
"enums",
"AppException",
"SAAuthError",
"FileChangedError",
"import_annotation",
"export_annotation",
Expand Down
Loading
Loading