Skip to content
Open
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
115 changes: 96 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,57 +50,134 @@ func getJoinToken(apiKey, apiSecret, room, identity string) (string, error) {
}
```

## RoomService API
## Authentication

RoomService gives you complete control over rooms and participants within them. It includes selective track subscriptions as well as moderation capabilities.
Every request to the server APIs is authenticated. `LiveKitAPI` (and each service client) supports two modes:

- **API key & secret** — recommended for backend use. The SDK signs a short-lived token per request from your key and secret. Keep your API secret on the server; never ship it to a client.
- **Access token** — for frontend / client-side use, where the API secret must not be exposed. Pass a pre-signed [access token](https://docs.livekit.io/frontends/reference/tokens-grants/) that already carries the grants for the operations you'll perform; the SDK sends it verbatim. Mint it on your backend and hand it to the client.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need something for generating a token with right permissions for different APIs if using this option?


```go
// Backend (API key & secret): set LIVEKIT_URL, LIVEKIT_API_KEY, and
// LIVEKIT_API_SECRET, then construct with no options...
api, _ := lksdk.NewLiveKitAPI()

// ...or pass any of them explicitly to override the corresponding env var:
api, _ := lksdk.NewLiveKitAPI(lksdk.WithURL(hostURL), lksdk.WithAPIKey("api-key", "api-secret"))

// Frontend (pre-signed access token): with LIVEKIT_URL set, pass just the token:
api, _ := lksdk.NewLiveKitAPI(lksdk.WithToken("token"))
```

## Server APIs

`LiveKitAPI` is a single entry point to every server API, exposing each service through an accessor: `Room()`, `Egress()`, `Ingress()`, `SIP()`, `AgentDispatch()`, and `Connector()`. Construct it with your credentials (see [Authentication](#authentication)); the url and credentials fall back to the `LIVEKIT_URL`, `LIVEKIT_API_KEY`, `LIVEKIT_API_SECRET`, and `LIVEKIT_TOKEN` environment variables. Values you pass explicitly take precedence; the environment variables are used only as a fallback for arguments you omit — an ambient `LIVEKIT_TOKEN`, for example, won't override an explicitly-provided API key and secret.

RoomService, reached via `api.Room()`, gives you complete control over rooms and participants within them, including selective track subscriptions and moderation capabilities.

```go
import (
"context"

lksdk "github.com/livekit/server-sdk-go/v2"
livekit "github.com/livekit/protocol/livekit"
)

func main() {
hostURL := "host-url" // ex: https://project-123456.livekit.cloud
apiKey := "api-key"
apiSecret := "api-secret"

hostURL := "host-url" // ex: https://project-123456.livekit.cloud
roomName := "myroom"
identity := "participantIdentity"

roomClient := lksdk.NewRoomServiceClient(hostURL, apiKey, apiSecret)
// authenticate with an API key and secret, or lksdk.WithToken("token") for a pre-signed token
api, err := lksdk.NewLiveKitAPI(lksdk.WithURL(hostURL), lksdk.WithAPIKey("api-key", "api-secret"))
if err != nil {
panic(err)
}

// create a new room
room, _ := roomClient.CreateRoom(context.Background(), &livekit.CreateRoomRequest{
// create a new room
room, _ := api.Room().CreateRoom(context.Background(), &livekit.CreateRoomRequest{
Name: roomName,
})

// list rooms
res, _ := roomClient.ListRooms(context.Background(), &livekit.ListRoomsRequest{})
// list rooms
rooms, _ := api.Room().ListRooms(context.Background(), &livekit.ListRoomsRequest{})

// terminate a room and cause participants to leave
roomClient.DeleteRoom(context.Background(), &livekit.DeleteRoomRequest{
// terminate a room and cause participants to leave
api.Room().DeleteRoom(context.Background(), &livekit.DeleteRoomRequest{
Room: roomName,
})

// list participants in a room
res, _ := roomClient.ListParticipants(context.Background(), &livekit.ListParticipantsRequest{
// list participants in a room
participants, _ := api.Room().ListParticipants(context.Background(), &livekit.ListParticipantsRequest{
Room: roomName,
})

// disconnect a participant from room
roomClient.RemoveParticipant(context.Background(), &livekit.RoomParticipantIdentity{
// disconnect a participant from room
api.Room().RemoveParticipant(context.Background(), &livekit.RoomParticipantIdentity{
Room: roomName,
Identity: identity,
})

// mute/unmute participant's tracks
roomClient.MutePublishedTrack(context.Background(), &livekit.MuteRoomTrackRequest{
// mute/unmute a participant's track
api.Room().MutePublishedTrack(context.Background(), &livekit.MuteRoomTrackRequest{
Room: roomName,
Identity: identity,
TrackSid: "track_sid",
Muted: true,
})

// other services are reached the same way, e.g. api.Egress(), api.SIP()
_, _ = api.Egress().ListEgress(context.Background(), &livekit.ListEgressRequest{})

_, _, _ = room, rooms, participants
}
```

### Agent dispatch

[Agent dispatch](https://docs.livekit.io/agents/server/agent-dispatch/) assigns an agent to a room. Explicit dispatch, via `api.AgentDispatch()`, gives you full control over when and how agents join and lets you pass job-specific metadata. The target agent is selected by its `agent_name`, and the room is created if it doesn't exist.

```go
// dispatch an agent into a room
dispatch, _ := api.AgentDispatch().CreateDispatch(context.Background(), &livekit.CreateAgentDispatchRequest{
Room: "myroom",
AgentName: "my-agent",
Metadata: "{}",
})

// list dispatches in a room
dispatches, _ := api.AgentDispatch().ListDispatch(context.Background(), &livekit.ListAgentDispatchRequest{
Room: "myroom",
})

// delete a dispatch
api.AgentDispatch().DeleteDispatch(context.Background(), &livekit.DeleteAgentDispatchRequest{
DispatchId: dispatch.Id,
Room: "myroom",
})

_ = dispatches
```

### Error handling

A failed server API call returns a `lksdk.ServerError`, which exposes the error code, message, and any server-provided metadata. Use `errors.As` to extract it. SIP dialing calls can fail with a SIP response status; `lksdk.SIPStatusFrom` extracts it from the returned error:

```go
_, err := api.SIP().CreateSIPParticipant(context.Background(), &livekit.CreateSIPParticipantRequest{
SipTrunkId: "trunk-id",
SipCallTo: "+15105550100",
RoomName: "my-room",
WaitUntilAnswered: true,
})
if err != nil {
if status := lksdk.SIPStatusFrom(err); status != nil {
fmt.Println(status.Code, status.Status) // e.g. 486 "Busy Here"
}
var se lksdk.ServerError
if errors.As(err, &se) {
fmt.Println(se.Code(), se.Msg())
}
}
```

Expand Down
2 changes: 1 addition & 1 deletion version.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

package lksdk

const Version = "2.17.0"
const Version = "2.18.0"

// userAgent identifies the SDK and version to the server on every request.
const userAgent = "livekit-server-sdk-go/" + Version
Loading