> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stmlink.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> 对外开放的服务端接口有两组前缀，都用同一套鉴权：`/server/v1/...`（SRTC 与 SMeeting 的主接口）和 `/stm/srvapi/v1/...`（SMeeting 的用户体系，服务端极简对接会用到）。鉴权是 app_id + nonce + timestamp + signature 四个请求头，用 app_key 做 HMAC-SHA256 签名，只能从业务方自己的后端调用。除这两组前缀外的接口均为内部接口，不要建议客户调用。 Public server APIs use two path prefixes with the same authentication: `/server/v1/...` (the main APIs of both SRTC and SMeeting) and `/stm/srvapi/v1/...` (the SMeeting user system, used by server-side low-code integration). Authenticate with four request headers, app_id + nonce + timestamp + signature, where signature is HMAC-SHA256 keyed with app_key; call these APIs only from the customer's own backend. Any other path is internal: never suggest calling it.
> app_key 是服务端密钥，绝不能出现在客户端代码、前端配置或移动 App 里。客户端加入频道用的 token 必须由业务方后端签发后下发（SRTC 走 `/server/v1/channel/grant`，SMeeting 走 `/stm/srvapi/v1/member/grant`）。 app_key is a server-side secret and must never appear in client code, frontend config, or a mobile app. The token a client uses to join must be issued by the customer's backend and passed down to the client (SRTC: `/server/v1/channel/grant`; SMeeting: `/stm/srvapi/v1/member/grant`).
> SRTC 与 SMeeting 是上下两层不同的产品，术语不通用：SRTC 是音视频底座，说「频道 channel」「加入 / 退出」；SMeeting 建在 SRTC 之上，说「房间 room」「会议 meeting」「进入 / 退出」。回答时按用户所在的层用对应术语，不要把「房间」「会议」安到 SRTC 的接口上，也不要用「频道」「加入 / 离开」描述 SMeeting 的概念（接口标识符原样保留）。 SRTC and SMeeting are two separate layers with different terminology. SRTC is the audio/video foundation: it has channels, and users join and leave a channel. SMeeting is built on top of SRTC: it has rooms and meetings, and members enter and exit a meeting. Answer in the terms of the layer the user is working with: never apply "room" or "meeting" to SRTC APIs, and never describe SMeeting concepts in prose with "channel", "join", or "leave" (API identifiers such as `force_join` keep their literal names).
> 同一能力在各端 SDK 里的包名、类名、方法名并不相同。写示例代码时请使用文档中该端自己的 API，不要把一个端的写法套到另一个端上。苹果平台每个产品都有两套 SDK（Swift 原生与 Objective-C），两套 API 不能混用。 Package, class, and method names differ between platform SDKs for the same capability. In sample code, use the API documented for that platform; never carry one platform's code over to another. On Apple platforms each product ships two SDKs (native Swift and Objective-C) whose APIs must not be mixed.

# Host controls

> What the host and co-hosts can do with the SMeeting Swift SDK: room-level controls such as mute all, camera off for everyone, and locking the meeting, member management, invitee reminders and calls, and inviting SIP / H.323 / GB28181 devices into the meeting. Read when building a host panel.

### Overview

APIs with the `admin` prefix require the host (`.host`) or co-host (`.coHost`) role; regular members who call them get a permission error from the server. Check before calling:

```swift theme={null}
let me = try? meeting.getUserInfo(meeting.currentUserId ?? "")
let isAdmin = me?.role == .host || me?.role == .coHost
```

Once a control action takes effect, **all members** receive the corresponding room / member state event. You don't need to change state manually on the initiating side; just refresh in the event handlers.

***

### Room-level controls

| API | Purpose | Room field | Change event |
| - | - | - | - |
| `adminUpdateRoomMicState(selfUnmuteMicDisabled:micDisabled:)` | Mute all | `micDisabled` / `selfUnmuteMicDisabled` | `roomMicStateDidChange` |
| `adminUpdateRoomCameraState(selfUnmuteCameraDisabled:cameraDisabled:)` | Camera off for everyone | `cameraDisabled` / `selfUnmuteCameraDisabled` | `roomCameraStateDidChange` |
| `adminUpdateRoomShareState(shareDisabled:)` | Disable sharing | `shareDisabled` | `roomShareStateDidChange` |
| `adminUpdateRoomChatDisabled(_:)` | Disable chat for everyone | `chatDisabled` | `roomChatDisabledDidChange` |
| `adminUpdateRoomScreenshotDisabled(_:)` | Disable screenshots | `screenshotDisabled` | `roomScreenshotDisabledDidChange` |
| `adminUpdateRoomWatermarkDisabled(_:)` | Turn off the watermark | `watermarkDisabled` | `roomWatermarkDisabledDidChange` |
| `adminUpdateRoomLocked(_:)` | Lock the meeting | `locked` | `roomLockedDidChange` |
| `adminUpdateEnterBeforeHostDisabled(_:)` | Disallow entering before the host | `enterBeforeHostDisabled` | No separate event |
| `adminStopRoomShare()` | Force the current sharing to end | `shareState` | `roomShareDidStop` |
| `adminDestroyRoom()` | End the whole meeting | — | Members receive `didDisconnect` |

#### The two switches of mute all

`micDisabled` and `selfUnmuteMicDisabled` mean different things, and together they determine the members' experience:

```swift theme={null}
// Mute all, and don't allow members to unmute themselves
try await meeting.adminUpdateRoomMicState(selfUnmuteMicDisabled: true, micDisabled: true)

// Mute all, but allow members to unmute themselves
try await meeting.adminUpdateRoomMicState(selfUnmuteMicDisabled: false, micDisabled: true)

// Turn off mute all
try await meeting.adminUpdateRoomMicState(selfUnmuteMicDisabled: false, micDisabled: false)
```

When "mute all" is turned on, the microphones of non-host members are turned off automatically. Whether members can then turn their microphones back on themselves depends on `selfUnmuteMicDisabled`. The camera follows the same rules.

#### End the meeting

```swift theme={null}
try await meeting.adminDestroyRoom()
```

All members are disconnected, and the member side learns about it through `meeting(_:didDisconnect:)`. The initiator also needs to take its own UI back out of the meeting.

***

### Member management

```swift theme={null}
// Change a member's in-meeting display name
try await meeting.adminUpdateUserName(targetId: uid, nickname: "Alice")

// Make a co-host / revoke
try await meeting.adminUpdateUserRole(targetId: uid, role: .coHost)
try await meeting.adminUpdateUserRole(targetId: uid, role: .member)

// Transfer host (after the transfer, you become a regular member)
try await meeting.adminMoveHost(targetId: uid)

// Disable chat for an individual member
try await meeting.adminUpdateUserChatDisabled(targetId: uid, chatDisabled: true)

// Prevent drawing
try await meeting.adminUpdateUserDrawDisabled(targetId: uid, drawDisable: true)

// Remove from the meeting; joinDisabled set to true also prevents entering again
try await meeting.adminKickUserOut(targetId: uid, joinDisabled: true)
```

The corresponding member state events: `userNameDidChange`, `userRoleDidChange`, `userChatDisabledDidChange`, `userDrawDisabledDidChange` (since 1.3.6). A removed member learns about it through `didDisconnect`.

Read the current drawing permission from `MeetingUserInfo.drawDisabled`; when it changes, you receive:

```swift theme={null}
func meeting(_ meeting: SMeetingEngine, userDrawDisabledDidChange data: UserDrawDisabledChangeEventData) {
    // data.uid, data.drawDisabled, data.opUid
}
```

For turning off a member's microphone / camera and asking members to turn them on, see [Raise hand and turn-on requests](/en/meeting/swift/advanced/handup).

***

### Change your own in-meeting display name

This action doesn't require the host role:

```swift theme={null}
try await meeting.updateName("New nickname")
```

***

### Invitee management

#### Update the invitee list

```swift theme={null}
try await meeting.adminUpdateConferee(meetingId: meetingId, conferee: [uid1, uid2])
```

#### Find out who hasn't entered yet

```swift theme={null}
let notEntered = try await meeting.meetNotEnter()
```

Returns `[NoEnterUserInfo]`, including nickname, phone number, avatar, role, and more.

#### Remind invitees to enter

```swift theme={null}
try await meeting.adminMeetRemind(uids: [uid1, uid2], useSms: true)
```

When `useSms` is `true`, an SMS reminder is sent as well.

#### In-meeting calls

```swift theme={null}
try await meeting.adminCallUsers(conferee: [uid1, uid2])
```

If the called users have enabled out-of-meeting messages, they receive the `imCallCalling` event; see [Out-of-meeting messages](/en/meeting/swift/advanced/im).

#### Online member list

```swift theme={null}
let page = try await meeting.adminListOnlineMember(page: 1, perPage: 20)
```

***

### Invite devices into the meeting

Meetings support bringing external devices into the meeting, such as SIP, H.323, GB28181, RTSP / RTMP pull streams, and file playback.

First, query the available devices:

```swift theme={null}
let devices = try await meeting.agentList(type: [.sip, .h323], name: "Meeting room")
```

Then send the invitation:

```swift theme={null}
try await meeting.adminInviteAgent(
    agents: [(type: .sip, contact: "sip:1001@example.com")],
    no: roomNo
)
```

For `AgentType` values, see [Types](/en/meeting/swift/types#agenttype). Read a device's current busy / idle status from `AgentInfo.status`.

***

### Related pages

* [Raise hand and turn-on requests](/en/meeting/swift/advanced/handup)
* [Waiting room](/en/meeting/swift/advanced/waiting-room)
* [Sub-meetings](/en/meeting/swift/advanced/sub-meetings)
* [API reference - Meeting management](/en/meeting/swift/api-reference/admin-actions)
