Skip to content

User Account Management API

sgofferj edited this page Aug 26, 2026 · 7 revisions

User Account Management API

Accessor: server.user

Reference: https://docs.tak.gov/api/takserver#tag/file-user-account-management-api

This API manages file-based user accounts and groups: create, update, delete, bulk-generate users, and read or replace group memberships.

Warning

Server quirk (5.7-RELEASE-43-HEAD): the endpoints below that accept group lists (create_or_update_file_user, create_file_users_in_bulk, update_users_for_group, update_groups_for_user) answer with HTTP 500 when any of the three group-list fields is omitted from the JSON body. The wrapper therefore always sends all three fields, using empty lists [] for those you do not pass. You normally never notice this - but if you call the raw API yourself, always include groupList, groupListIN and groupListOUT.

Tip

Groups are implicit: there is no create-group endpoint. A group appears automatically as soon as a user carries it (via create_or_update_file_user, create_file_users_in_bulk or the update_* operations) and disappears again once no user has it. To create a group, just create a user with that group - to delete it, remove it from all users. get_users_in_group() on a group nobody has returns HTTP 400, so check get_all_group_names() first.

Note

Direction semantics - IN and OUT are from the group's point of view, not the user's:

  • groupListIN - groups the user may send into (the writer side; a feed producer holds its feed group as IN, e.g. an ADSB feeder with the matching *_WRITE entitlement)
  • groupListOUT - groups whose traffic the user receives (the reader side; a consumer holds a feed channel as OUT)
  • groupList - both directions at once

create_or_update_file_user()

async def create_or_update_file_user(
    username: str,
    password: str,
    group_list_both: list[str] | None = None,
    group_list_in: list[str] | None = None,
    group_list_out: list[str] | None = None,
) -> tuple[int, Any]

Creates or updates a file-based user account. If the username already exists, its password and group membership are updated.

API: POST /user-management/api/new-user

Parameter Type Description
username str Username for the new/existing user
password str Password (the server enforces a password complexity policy: minimum 15 characters, must contain upper- and lowercase letters, a digit and a special character)
group_list_both list[str] or None Groups for both directions (API field groupList)
group_list_in list[str] or None Groups the user may send INTO (API field groupListIN)
group_list_out list[str] or None Groups whose traffic the user RECEIVES (API field groupListOUT)

Returns: (status_code, response)

Example:

# an analyst receives feed traffic but may not write into feeds
status, data = await srv.user.create_or_update_file_user(
    username="analyst",
    password="Strong-Pw-9!",
    group_list_out=["default"],
)

get_all_users()

async def get_all_users() -> tuple[int, Any]

Returns a list of all users registered on the server.

API: GET /user-management/api/list-users

Returns: (status_code, list_of_users) — each user is a dict with fields such as username, groups, etc.

Example:

status, users = await srv.user.get_all_users()
if status == 200:
    for u in users:
        print(u["username"])

get_all_group_names()

async def get_all_group_names() -> tuple[int, Any]

Returns a list of all group names defined on the server.

API: GET /user-management/api/list-groupnames

Returns: (status_code, list_of_groups) — each entry is a dict with a groupname field.

Example:

status, groups = await srv.user.get_all_group_names()
if status == 200:
    for g in groups:
        print(g["groupname"])

get_users_in_group()

async def get_users_in_group(group: str) -> tuple[int, Any]

Returns the members of a single group.

API: GET /user-management/api/users-in-group/{group}

Parameter Type Description
group str Group name

Returns: (status_code, SimpleGroupWithUsersModel) — a dict with groupname and the user-list fields (usersInGroupList, usersInGroupListIN, usersInGroupListOUT).

Example:

status, group = await srv.user.get_users_in_group("__ANONYMOUS__")
if status == 200:
    print(group["groupname"], group["usersInGroupList"])

get_groups_for_user()

async def get_groups_for_user(username: str) -> tuple[int, Any]

Returns the groups a single user belongs to.

API: GET /user-management/api/get-groups-for-user/{username}

Parameter Type Description
username str Username

Returns: (status_code, SimpleUserGroupModel) — a dict with username and the group-list fields (groupList, groupListIN, groupListOUT).

Example:

status, model = await srv.user.get_groups_for_user("analyst")
if status == 200:
    print(model["groupList"])

change_user_password()

async def change_user_password(username: str, password: str) -> tuple[int, Any]

Changes a user's password without touching group membership.

API: PUT /user-management/api/change-user-password

Parameter Type Description
username str Username
password str New password (same complexity policy as above)

Returns: (status_code, response)

Example:

status, _ = await srv.user.change_user_password("analyst", "Newer-Pw-9!")

delete_user()

async def delete_user(username: str) -> tuple[int, Any]

Deletes a user account.

API: DELETE /user-management/api/delete-user/{username}

Parameter Type Description
username str Username to delete

Returns: (status_code, response)

Example:

status, _ = await srv.user.delete_user("analyst")

Caution

there is no undo. Deleting a user removes its accounts, certificates and memberships.


create_file_users_in_bulk()

async def create_file_users_in_bulk(
    username_expression: str,
    start_n: int,
    end_n: int,
    group_list: list[str] | None = None,
    group_list_in: list[str] | None = None,
    group_list_out: list[str] | None = None,
) -> tuple[int, Any]

Generates a range of users in one call. The expression must contain the literal placeholder [N], which is replaced by each number from start_n to end_n (inclusive). This is handy for exercise rosters or drill groups.

API: POST /user-management/api/new-users

Parameter Type Description
username_expression str Username pattern, must contain [N], e.g. "drill-[N]"
start_n int First number substituted into [N]
end_n int Last number substituted into [N]
group_list list[str] or None Groups for both IN and OUT (API field groupList)
group_list_in list[str] or None Groups the user may send INTO (API field groupListIN)
group_list_out list[str] or None Groups whose traffic the user RECEIVES (API field groupListOUT)

Returns: (status_code, list_of_UserPasswordModel) — one dict per generated user with username and password (the server generates the passwords itself and returns them exactly once).

Example:

status, accounts = await srv.user.create_file_users_in_bulk(
    username_expression="drill-[N]",
    start_n=1,
    end_n=3,
    group_list=["__ANONYMOUS__"],
)
if status == 200:
    for account in accounts:
        print(account["username"], account["password"])

The bulk endpoint rejects requests without a non-empty group_list (HTTP 400, "No new user was created").


update_users_for_group()

async def update_users_for_group(
    groupname: str,
    users_in_group_list: list[str] | None = None,
    users_in_group_list_in: list[str] | None = None,
    users_in_group_list_out: list[str] | None = None,
) -> tuple[int, Any]

Replaces the user membership of a group.

API: PUT /user-management/api/update-group-users

Parameter Type Description
groupname str Group whose membership to replace
users_in_group_list list[str] or None Users for both IN and OUT (API field usersInGroupList)
users_in_group_list_in list[str] or None Users who may send INTO the group (API field usersInGroupListIN)
users_in_group_list_out list[str] or None Users who RECEIVE the group's traffic (API field usersInGroupListOUT)

Returns: (status_code, response)

Example:

status, _ = await srv.user.update_users_for_group(
    groupname="drill",
    users_in_group_list=["drill-1", "drill-2"],
)

update_groups_for_user()

async def update_groups_for_user(
    username: str,
    group_list: list[str] | None = None,
    group_list_in: list[str] | None = None,
    group_list_out: list[str] | None = None,
) -> tuple[int, Any]

Replaces the group membership of a user.

API: PUT /user-management/api/update-groups

Parameter Type Description
username str User whose membership to replace
group_list list[str] or None Groups for both IN and OUT (API field groupList)
group_list_in list[str] or None Groups the user may send INTO (API field groupListIN)
group_list_out list[str] or None Groups whose traffic the user RECEIVES (API field groupListOUT)

Returns: (status_code, response)

Example:

status, _ = await srv.user.update_groups_for_user(
    username="analyst",
    group_list=["default"],
)

user_exists()

async def user_exists(user: str) -> bool

Checks if a specific username exists on the server.

Parameter Type Description
user str Username to look up

Returns: True if a matching user exists, False otherwise.

Internally calls get_all_users() and searches by username field.

Note

If the underlying request fails (non-200 response), user_exists() returns False rather than raising - it cannot distinguish "absent" from "server error". Call get_all_users() yourself if you need to tell those cases apart.


group_exists()

async def group_exists(group: str) -> bool

Checks if a specific group name exists on the server.

Parameter Type Description
group str Group name to look up

Returns: True if a matching group exists, False otherwise.

Internally calls get_all_group_names() and searches by groupname field.

Note

As with user_exists(), a failing request yields False, not an exception.

Clone this wiki locally