LiveKit python-sdks: two packages, one monorepo, and what each one does
LiveKit real-time and server SDKs for Python
At a glance
- What is it?
- The LiveKit Python monorepo ships livekit (a real-time participant SDK) and livekit-api (token minting plus server APIs). This is what each package covers, how to install them, and where the design stops short.
- Who is it for?
- Adopt livekit-api if you run a backend that mints tokens, creates rooms or drives egress, ingress and SIP, and adopt livekit if a Python process must join a room as a participant. Skip both if you only need a browser client or a prebuilt agent runtime, since neither package replaces the LiveKit server.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 18, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The two packages solve different halves of a LiveKit integration
A LiveKit deployment has a server and clients. The Python monorepo splits its code along that line. The livekit package is the real-time SDK: a Python process connects to a room as a participant, publishes and subscribes to tracks, receives video frames through rtc.VideoStream, and registers or performs RPC methods. The livekit-api package is the server-side SDK: it mints access tokens with api.AccessToken, and it calls the server APIs for rooms, egress, ingress, SIP, agent dispatch and connectors through an api.LiveKitAPI object.
The audience is backend and agent developers. If you are writing a bot that joins a call, transcribes audio, or forwards function calls to a client, you need both packages in the same project. If you only create rooms and hand tokens to a browser, livekit-api alone is enough. The README states the split plainly: livekit is for connecting as a participant, livekit-api is for access token generation and server APIs. A third package, livekit-protocol, sits in the workspace and is pulled in as a dependency; the README does not document it separately, and the repository layout shows it as a sibling directory with its own version stream.
How tokens, rooms and RPC calls actually flow
Token minting is synchronous and builder-style. api.AccessToken() reads LIVEKIT_API_KEY and LIVEKIT_API_SECRET from the environment when you do not pass them, then with_identity, with_name and with_grants attach claims, and to_jwt() returns the string. The grants decide what the holder may do; the README's example sets room_join and names a room. This token is what a client passes to room.connect(URL, TOKEN).
Server calls go the other way. LiveKitAPI is an async client built on asyncio and aiohttp, so it must run inside an event loop. One object fans out into named services: lkapi.room, lkapi.egress, lkapi.ingress, lkapi.sip, lkapi.agent_dispatch, lkapi.connector. Each call takes a request object, such as api.CreateRoomRequest(name="my-room"), and returns a response object. Authentication accepts an API key and secret for backend use, or a pre-signed token via LiveKitAPI.with_token for client-side use where the API secret must not be exposed. Omitted values fall back to LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET and LIVEKIT_TOKEN.
On the real-time side, the flow is event-driven. rtc.Room() emits participant_connected and track_subscribed. When a video track arrives, the handler wraps it in rtc.VideoStream(track) and iterates frames with async for. Autosubscribe is on by default, and the README warns that participants and tracks already present when you connect do not fire those events; you read room.remote_participants and each participant's track_publications instead. That distinction between live events and initial state is the part most first integrations get wrong.
Install and mint your first token
Both packages are on PyPI under their own names, so they install independently. The README shows the server package first.
pip install livekit-apiWith the package installed, set LIVEKIT_API_KEY and LIVEKIT_API_SECRET in the environment and the builder picks them up automatically. The README's example produces a JWT for a participant named python-bot with permission to join my-room.
from livekit import api
token = api.AccessToken() \
.with_identity("python-bot") \
.with_name("Python Bot") \
.with_grants(api.VideoGrants(
room_join=True,
room="my-room",
)).to_jwt()The result is a signed string. Pass it to a client, or to the real-time SDK's room.connect. If the environment variables are missing, the README does not describe the failure mode, so treat token creation as a step worth checking in isolation before wiring it into a request handler.
Create a room from Python and list what exists
Room creation needs an event loop because RoomService is async. The README's example builds a LiveKitAPI against a cloud URL, creates a room, lists rooms, and closes the client. Note the explicit aclose call: nothing in the example suggests a context manager, so the connection is yours to close.
from livekit import api
import asyncio
async def main():
lkapi = api.LiveKitAPI("https://my-project.livekit.cloud")
room_info = await lkapi.room.create_room(
api.CreateRoomRequest(name="my-room"),
)
print(room_info)
results = await lkapi.room.list_rooms(api.ListRoomsRequest())
print(results)
await lkapi.aclose()
asyncio.run(main())Run it and you should see the created room's info printed, followed by the room list. For a self-hosted server, the URL is your own endpoint rather than a livekit.cloud host. The same object exposes egress, ingress, sip, agent_dispatch and connector as attributes, so the pattern repeats across services: build a request, await the call, handle the error.
Error handling splits SIP failures from everything else
The README documents two exception types. A failed server API call raises api.ServerError, which exposes code, message and any server-provided metadata. A failed SIP dial raises api.SipCallError, a ServerError subclass that adds sip_status_code, so a busy line can be distinguished from a generic failure. The README's example catches SipCallError first, checks for 486, then falls through to ServerError for anything else. That ordering matters: catching the parent first would swallow the SIP-specific branch.
try:
await lkapi.sip.create_sip_participant(api.CreateSIPParticipantRequest(
sip_trunk_id="ST_...",
sip_call_to="+15105550100",
room_name="my-room",
wait_until_answered=True,
))
except api.SipCallError as e:
print(e)
if e.sip_status_code == 486:
...
except api.ServerError as e:
print(e.code, e.message)The wait_until_answered flag is what makes the dial block until there is a SIP outcome to report. Without it, the README gives no detail on when the error surfaces, so if your code depends on knowing the call failed, keep that flag on and handle both exception types.
Where the Python SDKs are the wrong tool
The real-time package is a participant SDK, not a media server. It does not host rooms; it connects to a LiveKit server, cloud or self-hosted. If you need to run the server itself, this repository is not that. The README points to LiveKit Cloud or a self-hosted server as the thing you connect to.
There is also a packaging constraint worth knowing before you plan an upgrade path. The three packages version independently: the release list shows api-v1.2.0, protocol-v1.1.18 and rtc-v1.1.7 as separate tags. Nothing in the README promises that matching minor numbers across packages are compatible, so a project that pins all three should read the release notes for each rather than assume a shared version line. The monorepo's own pyproject.toml declares requires-python >= 3.9, so older interpreters are out.
Finally, the README is uneven. It documents tokens, rooms, authentication, error handling, room connection and RPC. It does not document rollback, retry behaviour, rate limits, or how aclose interacts with in-flight calls. The examples/ directory is where the rest lives: there are files for egress-style API calls, data streams, data tracks, E2EE, webhooks, agent dispatch, participant attributes and publishing audio and video. Treat the README as an entry point and the examples as the reference.
livekit-api against the browser client SDK and raw HTTP
The obvious alternative for token minting is the JavaScript client SDK, which is what most browser front ends already use. The difference is where the secret lives. The Python package is designed for backend use with an API key and secret, or for client-side use with a pre-signed token where the secret must not be exposed; the README states that constraint directly. A browser bundle cannot hold the secret, so the minting step belongs on a server in either design. The Python package is the right side of that boundary when your backend is Python.
The second alternative is calling the LiveKit server API over HTTP yourself. That is possible in principle, but you would reimplement the request and response objects, the environment-variable fallbacks for LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET and LIVEKIT_TOKEN, and the typed error split between ServerError and SipCallError. The Python package is a thin typed layer over exactly that. If your service is not Python, this repository gives you nothing; the protocol package is a dependency of these SDKs, not a standalone HTTP client you would hand to a Go or Node service.
Maintenance, licensing and what to check before upgrading
The repository is not archived, and the last push was on 2026-09-15, two days before this writing. The most recent tagged release in the list is api-v1.2.0 from 2026-07-14, followed by protocol-v1.1.18 on 2026-05-13 and rtc-v1.1.7 on 2026-04-28. Those dates are close enough that the project is being worked on, but the release cadence is not uniform across the three packages, and the README does not publish a compatibility matrix. If you pin versions, pin all three and check the release notes for the package you are actually changing.
Everything here is Apache-2.0, with a NOTICE file at the repository root. That permits commercial use and modification, and it requires that you keep the licence and NOTICE with redistributed copies. This is a description of the licence text, not legal advice; if you are redistributing a modified build, have your own counsel read the terms.
The upgrade cost is mostly version skew. Because livekit, livekit-api and livekit-protocol ship as separate PyPI packages, a pip install livekit-api upgrade can move one package while the others stay put. The workspace's uv.lock and the tool.uv.sources entries in pyproject.toml show how the maintainers keep them aligned in development, but that mechanism is for contributors, not for consumers. Consumers get three independent version numbers and no stated compatibility guarantee.
Editorial conclusion
Adopt livekit-api if you run a backend that mints tokens, creates rooms or drives egress, ingress and SIP, and adopt livekit if a Python process must join a room as a participant. Skip both if you only need a browser client or a prebuilt agent runtime, since neither package replaces the LiveKit server. Before committing, check the pinned versions of livekit, livekit-api and livekit-protocol in your lockfile, confirm your Python is 3.9 or newer, and read the examples/ directory for the service you plan to call, because the README covers only room creation, tokens and RPC in detail.
Frequently asked questions
What is a Python SDK, in the context of LiveKit python-sdks?
It is a Python package that wraps a service's protocol so you call typed objects instead of raw requests. This monorepo ships two: livekit for joining a room as a participant, and livekit-api for access tokens and server APIs.
Are SDKs and APIs the same?
No. The API is the server-side surface, and the SDK is the client code that calls it. In this repository livekit-api is the SDK that talks to the LiveKit server API, and the README separates that from livekit, which connects to a room as a participant.
What are some examples of SDKs in this repository?
The two published packages are examples in themselves: livekit on PyPI for real-time participation, and livekit-api on PyPI for token generation and server calls. The repository also carries an examples/ directory with files for RPC, E2EE, webhooks, data streams and agent dispatch.
How do I create a Python SDK of my own?
This repository does not document that. Its own packages are built from the livekit-rtc, livekit-api and livekit-protocol directories in a uv workspace, with ruff and mypy configured in pyproject.toml, but the README offers no guidance on building a separate SDK.
Community notes