@@ -122,6 +122,12 @@ async def create_column(
122122 selection_options : Optional [str ] = None ,
123123 selection_default : Optional [str ] = None ,
124124 datetime_default : Optional [str ] = None ,
125+ usergroup_default : Optional [str ] = None ,
126+ usergroup_multiple_items : Optional [bool ] = None ,
127+ usergroup_select_users : Optional [bool ] = None ,
128+ usergroup_select_groups : Optional [bool ] = None ,
129+ usergroup_select_teams : Optional [bool ] = None ,
130+ usergroup_show_user_status : Optional [bool ] = None ,
125131 ):
126132 """
127133 Create a new column in a table.
@@ -138,6 +144,14 @@ async def create_column(
138144 - text columns: text_default, text_max_length
139145 - selection columns: selection_options (JSON string, e.g. '[{"id": 1, "label": "Option A"}]'), selection_default
140146 - datetime columns: datetime_default (ISO 8601 format)
147+ - usergroup columns: set usergroup_select_users / usergroup_select_groups / usergroup_select_teams
148+ to True for each entity type the Tables UI should offer in its picker (these are UI hints
149+ only — the API itself does NOT enforce them on row writes). usergroup_multiple_items
150+ controls whether the UI allows > 1 entry per cell (also UI-only, not server-enforced).
151+ usergroup_default is a JSON string matching the row-value shape (defaults to empty).
152+ usergroup_show_user_status toggles whether the UI renders an online/away dot (cosmetic).
153+ Send all four boolean flags explicitly when creating a usergroup column — leaving them
154+ at their None default produces a column the Tables UI treats as misconfigured.
141155
142156 :param table_id: the id of the table (obtainable with list_tables)
143157 :param title: the column title
@@ -179,6 +193,18 @@ async def create_column(
179193 payload ['selectionDefault' ] = selection_default
180194 if datetime_default is not None :
181195 payload ['datetimeDefault' ] = datetime_default
196+ if usergroup_default is not None :
197+ payload ['usergroupDefault' ] = usergroup_default
198+ if usergroup_multiple_items is not None :
199+ payload ['usergroupMultipleItems' ] = usergroup_multiple_items
200+ if usergroup_select_users is not None :
201+ payload ['usergroupSelectUsers' ] = usergroup_select_users
202+ if usergroup_select_groups is not None :
203+ payload ['usergroupSelectGroups' ] = usergroup_select_groups
204+ if usergroup_select_teams is not None :
205+ payload ['usergroupSelectTeams' ] = usergroup_select_teams
206+ if usergroup_show_user_status is not None :
207+ payload ['usergroupShowUserStatus' ] = usergroup_show_user_status
182208 response = await nc ._session ._create_adapter ().request (
183209 'POST' , f"{ nc .app_cfg .endpoint } /index.php/apps/tables/api/1/tables/{ table_id } /columns" ,
184210 headers = {"Content-Type" : "application/json" , "OCS-APIREQUEST" : "true" },
@@ -193,9 +219,25 @@ async def update_column(
193219 title : Optional [str ] = None ,
194220 mandatory : Optional [bool ] = None ,
195221 description : Optional [str ] = None ,
222+ usergroup_default : Optional [str ] = None ,
223+ usergroup_multiple_items : Optional [bool ] = None ,
224+ usergroup_select_users : Optional [bool ] = None ,
225+ usergroup_select_groups : Optional [bool ] = None ,
226+ usergroup_select_teams : Optional [bool ] = None ,
227+ usergroup_show_user_status : Optional [bool ] = None ,
196228 ):
197229 """
198- Update a column's properties
230+ Update a column's properties.
231+
232+ For usergroup columns, the same six usergroup_* flags accepted by create_column may
233+ be updated here (e.g. to widen which entity types the UI picker accepts, or to flip
234+ multi-select on/off). All flags remain UI hints — see create_column for details.
235+
236+ IMPORTANT: The Tables API resets any usergroup flag NOT included in this request to
237+ null. To preserve existing usergroup configuration while changing one flag, call
238+ list_columns first and re-send every usergroup_* flag that should keep its current
239+ value alongside the one(s) you want to change.
240+
199241 :param column_id: the id of the column to update (obtainable with list_columns)
200242 :param title: new title for the column
201243 :param mandatory: whether this column is required
@@ -209,6 +251,18 @@ async def update_column(
209251 payload ['mandatory' ] = mandatory
210252 if description is not None :
211253 payload ['description' ] = description
254+ if usergroup_default is not None :
255+ payload ['usergroupDefault' ] = usergroup_default
256+ if usergroup_multiple_items is not None :
257+ payload ['usergroupMultipleItems' ] = usergroup_multiple_items
258+ if usergroup_select_users is not None :
259+ payload ['usergroupSelectUsers' ] = usergroup_select_users
260+ if usergroup_select_groups is not None :
261+ payload ['usergroupSelectGroups' ] = usergroup_select_groups
262+ if usergroup_select_teams is not None :
263+ payload ['usergroupSelectTeams' ] = usergroup_select_teams
264+ if usergroup_show_user_status is not None :
265+ payload ['usergroupShowUserStatus' ] = usergroup_show_user_status
212266 response = await nc ._session ._create_adapter ().request (
213267 'PUT' , f"{ nc .app_cfg .endpoint } /index.php/apps/tables/api/1/columns/{ column_id } " ,
214268 headers = {"Content-Type" : "application/json" , "OCS-APIREQUEST" : "true" },
@@ -263,6 +317,19 @@ async def create_row(table_id: int, data: str):
263317 Create a new row in a table.
264318 The data parameter must be a JSON object mapping column IDs to their values.
265319 Use list_columns first to find the column IDs for the target table.
320+
321+ For usergroup columns, the value MUST be a JSON array of objects, each with keys
322+ `id` (string) and `type` (integer). Even for single-select columns
323+ (usergroupMultipleItems=false) a one-element array is required; an empty array []
324+ clears the cell. `type` is: 0 = user, 1 = group, 2 = team (Circle). No other integers
325+ are valid — values like type:7 are silently persisted but no Tables UI renders them.
326+ For type=0, `id` is the bare NC user_id (e.g. "alice"). For type=1, `id` is the
327+ group_id (e.g. "developers"). For type=2, `id` is the team's `singleId` — a 31-char
328+ string from the Circles app (e.g. "X4m8PoyzRrfxMcN6EqbTTAGSES7doAO"), NOT the team's
329+ display name. Display names are not resolved by the server. Example for a usergroup
330+ column with id 5 containing user `alice` and group `developers`:
331+ '{"5": [{"id": "alice", "type": 0}, {"id": "developers", "type": 1}]}'
332+
266333 :param table_id: the id of the table (obtainable with list_tables)
267334 :param data: JSON object mapping column IDs to values, e.g. '{"1": "some text", "2": 42, "3": "2026-01-15"}'
268335 :return: the created row
@@ -282,6 +349,14 @@ async def update_row(row_id: int, data: str, view_id: Optional[int] = None):
282349 Update an existing row's data.
283350 The data parameter must be a JSON object mapping column IDs to their new values.
284351 Only include columns you want to change.
352+
353+ For usergroup columns, the value MUST be a JSON array of objects with keys `id`
354+ (string) and `type` (integer): 0 = user, 1 = group, 2 = team (Circle). An empty
355+ array [] clears the cell. Other type integers are silently persisted but unusable.
356+ For type=2 the `id` is the team's `singleId` (31-char string from the Circles app),
357+ not the team's display name. Example updating column id 5 to a single user:
358+ '{"5": [{"id": "alice", "type": 0}]}'
359+
285360 :param row_id: the id of the row to update (obtainable with list_rows)
286361 :param data: JSON object mapping column IDs to new values, e.g. '{"1": "updated text", "3": "2026-02-20"}'
287362 :param view_id: optional view id for permission context
0 commit comments