Qriib Meet — Python integration guide
qriib-meet is the Python package a backend uses to create and manage Qriib
rooms, then hand the returned meeting link to the client application that
opens the embedded Qriib meeting.
from qriib_meet import QriibMeetClient
It is the server-side counterpart of the qriib_meet Flutter package. Every
resource, method, model, and error keeps the same name in snake_case, so a
team that knows one SDK can read the other.
Before you start
qriib-meet runs on Python 3.10 or newer. The API client signs management
requests with Qriib credentials, while a meeting is opened on a device with the
fresh final_link returned by the Qriib API.
A Python process has no camera, microphone, or screen, so the embedded meeting
UI is not part of this package. Create rooms here, then pass the final_link
to your Flutter app, which opens it with client.meetings.join.
For a production service, do not hard-code organization or project secret
keys in source control. Keep them in a secrets manager or environment
configuration, and never log a final_link.
Installation
pip install qriib-meet
Import only the public package entry point:
from qriib_meet import QriibMeetClient
Five-minute integration
- Create one
QriibMeetClientwhen your service starts. - Call a room API such as
create_quick_video_roomorjoin_room. - Read the server-returned
final_linkand return it to your client app. - The Flutter
qriib_meetpackage opens the full-screen meeting from it.
from qriib_meet import (
QriibApiException,
QriibMeetClient,
QriibMeetException,
QriibRoomMetadata,
)
qriib = QriibMeetClient.with_project_credentials(
api_key="YOUR_PROJECT_API_KEY",
secret_key="YOUR_PROJECT_SECRET_KEY",
base_url="https://api.qriib.dev",
enable_network_logging=False,
)
def start_call(ticket_id: str) -> dict[str, str | None]:
try:
response = qriib.rooms.create_quick_video_room(
project_id="YOUR_PROJECT_ID",
client_room_id=f"support-call-{ticket_id}",
metadata=QriibRoomMetadata(room_title="Support call"),
)
final_link = qriib.meetings.link_from_response(response)
return {"room_id": response.get("room_id"), "final_link": final_link}
except QriibMeetException as error:
raise RuntimeError(error.message) from error
except QriibApiException as error:
raise RuntimeError(error.message) from error
client_room_id must be unique in the selected project. Use an ID from your
backend domain, for example an order, appointment, or support-ticket ID, or
generate one with new_client_room_id().
What it provides
QriibMeetClient— API client that can use project and organization credentials (also aliased asQriibClientandVCloudClient).client.rooms— create, schedule, start, join, inspect, and end rooms.client.meetings— validates the server-issuedfinal_linkthat the client application opens.client.branding— upload and update project branding logos and icons.client.analytics,client.projects, andclient.recordings— management and reporting endpoints.
Credentials and resource access
The client automatically signs the appropriate requests. You do not create
your own HTTP client, headers, key, or hash-signature values.
| Resource | Required credentials | Main use |
|---|---|---|
client.rooms |
Project | Create, join, schedule, inspect, and end rooms |
client.meetings |
None; validates a fresh server final_link |
Hand the meeting link to the client app |
client.branding |
Project | Create and update project branding assets |
client.analytics |
Project | Read room analytics |
client.recordings |
Project | Read recording data and links |
client.projects |
Organization | Create and manage projects |
Use with_project_credentials for room-only services. Use with_credentials
when the same service also calls organization/project-management operations.
Create the client once
Create one client for the selected Qriib project and close it with the service or dependency container that owns it. The client is also a context manager.
from qriib_meet import QriibMeetClient
qriib = QriibMeetClient.with_project_credentials(
api_key="YOUR_PROJECT_API_KEY",
secret_key="YOUR_PROJECT_SECRET_KEY",
base_url="https://api.qriib.dev",
enable_network_logging=True,
timeout=30.0,
)
# ... later, on shutdown
qriib.close()
# or
with QriibMeetClient.with_project_credentials(api_key="...", secret_key="...") as qriib:
...
enable_network_logging emits request/response summaries on the qriib_meet
logger at INFO level. Disable it in production. Never hard-code or log
project credentials, final_link values, or decoded meeting tokens.
Create a quick video room and return its link
Quick rooms return a final_link. Pass that complete string unchanged to the
client application; do not decode the token yourself.
from qriib_meet import QriibRoomMetadata, new_client_room_id
response = qriib.rooms.create_quick_video_room(
project_id="YOUR_PROJECT_ID",
client_room_id=new_client_room_id(), # Unique inside the project.
name="Support call",
moderator_id="moderator-42",
max_participants=20,
empty_timeout=1_000,
metadata=QriibRoomMetadata(
room_title="Support call",
welcome_message="Welcome to the call",
room_duration=60,
),
)
final_link = qriib.meetings.link_from_response(response)
room_id = response.get("room_id")
Use create_quick_audio_room in the same way for an immediate audio room.
Join an existing room
join_room returns the participant-specific final_link used to open the
meeting. The role is sent as user_metadata.role.
from qriib_meet import QriibUserInfo
response = qriib.rooms.join_room(
room_id="ROOM_ID",
user_info=QriibUserInfo(
name="Karim",
role="attendee",
is_admin=False,
is_hidden=False,
),
)
final_link = qriib.meetings.link_from_response(response)
Scheduled rooms
Creating a scheduled room is not the same as starting a meeting:
create scheduled room -> room_id
start scheduled room -> final_link
open Qriib meeting -> client app opens final_link
Create the schedule and store the returned room_id in your own backend:
scheduled = qriib.rooms.create_scheduled_video_room(
project_id="YOUR_PROJECT_ID",
client_room_id="order-123-scheduled-video",
start_at="2026-12-31T18:30", # Local ISO-8601 minute precision.
max_participants=20,
empty_timeout=1_000,
metadata=QriibRoomMetadata(room_title="Scheduled review"),
)
room_id = scheduled["room_id"]
When the room is started, return its meeting link:
started = qriib.rooms.start_scheduled_room(room_id, name="Scheduled review")
final_link = qriib.meetings.link_from_response(started)
Use create_scheduled_audio_room for scheduled audio rooms. If the server does
not return final_link from start_scheduled_room, call join_room with the
started room_id and use the link from that join response.
Other room operations
client.rooms currently provides these methods:
| Category | Methods |
|---|---|
| Create | create_quick_audio_room, create_quick_video_room, create_scheduled_audio_room, create_scheduled_video_room |
| Enter/share | join_room, create_invitation_link |
| Scheduled | start_scheduled_room |
| Inspect | get_room_status, get_active_room_info, get_active_rooms_info, fetch_past_rooms |
| End | end_room |
All resource methods return dict[str, Any]. This deliberately preserves the
server response while API response schemas remain flexible. Read only the
fields your integration needs, such as room_id and final_link.
fetch_past_rooms takes from_ for the API's from field because from is a
Python keyword.
Analytics, projects, and recordings
client.analytics.get_analytics(room_id=...) and all client.recordings
methods require project credentials. Project management methods require
organization credentials, so initialize the client with both scopes when your
service uses all resources:
from qriib_meet import (
QriibMeetClient,
QriibOrganizationCredentials,
QriibProjectCredentials,
)
qriib = QriibMeetClient.with_credentials(
organization=QriibOrganizationCredentials(
api_key="YOUR_ORGANIZATION_API_KEY",
secret_key="YOUR_ORGANIZATION_SECRET_KEY",
),
project=QriibProjectCredentials(
api_key="YOUR_PROJECT_API_KEY",
secret_key="YOUR_PROJECT_SECRET_KEY",
),
)
analytics = qriib.analytics.get_analytics(room_id="ROOM_ID")
recordings = qriib.recordings.get_records(project_id="PROJECT_ID")
project = qriib.projects.get_project(project_id="PROJECT_ID")
Update a project by supplying at least one documented field. Nested settings are passed as JSON-shaped collections because their inner schema is API-owned:
qriib.projects.update_project(
project_id="PROJECT_ID",
default_project=True,
webhook_url="https://example.com/qriib-webhook",
room_features=[{"chat": True}],
default_lock_settings={"locked": True},
)
Change a project's status with QriibProjectStatus:
from qriib_meet import QriibProjectStatus
qriib.projects.update_project_status(
project_id="PROJECT_ID",
status=QriibProjectStatus.inactive,
)
Meeting behavior
client.meetings cannot open a meeting from a Python process. It offers:
| Method | Use |
|---|---|
validate_final_link(final_link) |
Returns the trimmed link, or raises QriibMeetException when it has no meeting token. |
link_from_response(response) |
Reads final_link from a room response, direct or inside a data envelope, and validates it. |
Return the complete fresh final_link to the participant's device. Never send
only a decoded token, a room ID, or an invitation URL to the client's
meetings.join: it requires the complete link returned by the server for that
participant.
Errors
Handle SDK errors at the call site and show only safe messages to the user:
try:
final_link = start_call("123")
except QriibMeetException as error:
show_message(error.message)
except QriibApiException as error:
show_message(error.message)
QriibMeetException covers local validation, including a missing or malformed
meeting link. QriibSessionException and QriibNetworkException are
meeting-specific subclasses kept for parity with the Flutter package.
QriibApiException represents a failed API request and includes the server
response and HTTP status for application-level error handling. Typed
subclasses map common statuses:
| Status | Exception |
|---|---|
| 400, 422 | QriibValidationException |
| 401, 403 | QriibAuthenticationException |
| 404 | QriibNotFoundException |
| 429 | QriibRateLimitException |
| other | QriibApiException |
For API errors, prefer error.message; it contains a meaningful server message
when one is available, for example Client room ID already exists. Do not show
or log raw request credentials or meeting links.
Development
pip install -e ".[dev]"
pytest
ruff check .
mypy src
Release files for qriib-meet 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| qriib_meet-1.1.0.tar.gz | 22.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| qriib_meet-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 47.6 kB
Release files / qriib_meet-1.1.0.tar.gz
| Download URL | qriib_meet-1.1.0.tar.gz |
|---|---|
| Size | 22.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7821cc5ce9145917eade1eb6ee36534c3d5132ab4a5820455162c2ffca5a7baa
|
|
BLAKE2b-256 checksum How to use checksums |
363a01eb80dcf25584bf3843e99256b7ef9223ea42e53725e50e73e45345b263
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / qriib_meet-1.1.0-py3-none-any.whl
| Download URL | qriib_meet-1.1.0-py3-none-any.whl |
|---|---|
| Size | 24.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f62f3241e8d371c8989741aa5a33350991fd789716d88443b2de389efc1fb2c8
|
|
BLAKE2b-256 checksum How to use checksums |
3db7f8163ccc0875eea0d8e733d91ffaf8061f5e2adafb37527aa3d12aea5186
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|