const callType = 'default';
const callId = 'my-first-call';
const call = client.video.call(callType, callId);
call.create({ data: { created_by_id: 'john' } });
// optionally provide additional data
call.create({
data: {
created_by_id: 'john',
// Call members need to be existing users
members: [{ user_id: 'john', role: 'admin' }, { user_id: 'jack' }],
custom: {
color: 'blue',
},
},
});
// Upsert behavior
call.getOrCreate({data: /* */});
Calls
Creating calls
You can create a call by providing the call type and an ID:
- The call type controls which features are enabled and sets up permissions. Call type settings and permissions can be set from API, or using the Stream Dashboard.
- Calls can be used once or multiple times depending on your app. Unless you want to re-use the same call multiple times, the recommended way to pick a call ID is to use a uuid v4 so that each call gets a unique random ID.
You can specify call members who can receive push notification about the call.
It’s also possible to store any custom data with the call object.
import uuid
from getstream.models.call_request import CallRequest
call = client.video.call("default", uuid.uuid4())
call.create(
data=CallRequest(
created_by_id="sacha",
),
)
# optionally provide additional data
call.create(
data=CallRequest(
created_by_id="sacha",
# note: you can add users as members to calls to support more complex permissions
members=[
MemberRequest(user_id="john", role="admin"),
MemberRequest(user_id="jack"),
],
custom={"color": "blue"},
),
)
import (
"github.com/GetStream/getstream-go"
"github.com/google/uuid"
)
call := client.Video().Call("default", uuid.NewString())
members := []getstream.MemberRequest{
{UserID: "john", Role: getstream.PtrTo("admin")},
{UserID: "jack"},
}
callRequest := getstream.GetOrCreateCallRequest{
Data: &getstream.CallRequest{
CreatedByID: getstream.PtrTo("sacha"),
Members: members,
Custom: map[string]any{
"color": "blue",
},
},
}
response, err := call.GetOrCreate(ctx, &callRequest)
# Gets or creates a call
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${CALL_TYPE}/${CALL_ID}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "Content-Type: application/json" \
-H "stream-auth-type: jwt" \
-d '{
"data": {
"created_by_id": "sacha@getstream.io",
"members": [
{ "role": "admin", "user_id": "sacha@getstream.io" }
],
"custom": { "color": "blue" }
}
}'
ring
flag
To start the ringing flow, we need to set the ring
flag to true
and provide the list of members we want to call. It is important to note that the caller should also be included in the list of members.
// or call.create
// or call.get
await client.call("default", "test-outgoing-call").getOrCreate({
ring: true,
data: {
created_by_id: "myself",
members: [{ user_id: "myself" }, { user_id: "my friend" }],
},
});
from getstream.models import CallRequest, MemberRequest
call.get_or_create(
data=CallRequest(
created_by_id=user_id,
members=[MemberRequest(user_id=alice.id), MemberRequest(user_id=bob.id)],
),
ring=True
)
call.GetOrCreate(ctx, &getstream.GetOrCreateCallRequest{
Ring: getstream.PtrTo(true),
Data: &getstream.CallRequest{
CreatedByID: getstream.PtrTo("myself"),
Members: []getstream.MemberRequest{
{UserID: "myself"},
{UserID: "my friend"},
},
},
})
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${CALL_TYPE}/${CALL_ID}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "Content-Type: application/json" \
-H "stream-auth-type: jwt" \
-d '{
"ring": true,
"data": {
"created_by_id": "myself",
"members": [{ "user_id": "myself" }, { "user_id": "my friend" }]
}
}'
This step will start the signaling flow and send the call.ring
WebSocket event. It’s also possible to send push notifications to call members on this event, for more information see the Call Types page.
Call members can decide to accept or reject the incoming call. The callee can decide to cancel the outgoing call (for more information see the SDK documentations).
notify
flag
Setting the notify
flag to true
will send the call.notification
WebSocket event. It’s also possible to send push notifications to call members on this event, for more information see the Call Types page.
// or call.create
// or call.get
await client.call("default", "test-outgoing-call").getOrCreate({
notify: true,
data: {
created_by_id: "myself",
members: [{ user_id: "myself" }, { user_id: "my friend" }],
},
});
from getstream.models import CallRequest, MemberRequest
call.get_or_create(
data=CallRequest(
created_by_id=user_id,
members=[MemberRequest(user_id=alice.id), MemberRequest(user_id=bob.id)],
),
notify=True
)
call.GetOrCreate(ctx, &GetOrCreateCallRequest{
Notify: getstream.PtrTo(true),
Data: &CallRequest{
CreatedByID: getstream.PtrTo("myself"),
Members: []getstream.MemberRequest{
{UserID: "myself"},
{UserID: "my friend"},
},
},
})
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${CALL_TYPE}/${CALL_ID}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "Content-Type: application/json" \
-H "stream-auth-type: jwt" \
-d '{
"notify": true,
"data": {
"created_by_id": "myself",
"members": [{ "user_id": "myself" }, { "user_id": "my friend" }]
}
}'
Call types
Call types provide sensible default settings for different use-cases. We provide the following types out of the box:
- Default (
default
) for 1:1 or group calls that use both video and audio - Livestreaming (
livestream
) to build ultra low latency livestreaming for your app on our global edge network. Broadcast from your phone or RTMP and scale to millions of participants. - Audio room (
audio_room
) to build audio experiences for your app. You can build basic calling or feature rich experience like Twitter spaces. Audio quality, reliability and scalability is far ahead of competing solutions. - Development (
development
) This call type comes with almost all permission settings disabled so that it is simpler to get your initial implementation up and running. You should only use this call type early-on during development.
Each of our SDKs have tutorials specific for each call type. If you want to know the default settings for each of the call types check out the Built-in call types page.
It’s possible to tweak the built-in call types or create new ones.
Updating calls
Default call settings are inherited from the call type. These settings can be overridden if necessary.
call.update({
settings_override: {
audio: { mic_default_on: true, default_device: "speaker" },
},
});
// or to update custom data
call.update({ custom: { color: "red" } });
from getstream.models import CallSettingsRequest
# update some custom data for this call
call.update(custom={'color': 'red'})
# update settings for this call
call.update(
settings_override=CallSettingsRequest(
screensharing=ScreensharingSettingsRequest(
enabled=True, access_request_enabled=True
),
),
)
// update some custom data for this call
response, err := call.Update(ctx, &getstream.UpdateCallRequest{
Custom: map[string]any{"color": "red"},
})
// update settings for this call
response, err = call.Update(ctx, &getstream.UpdateCallRequest{
SettingsOverride: &getstream.CallSettingsRequest{
Screensharing: &getstream.ScreensharingSettingsRequest{
Enabled: getstream.PtrTo(true),
AccessRequestEnabled: getstream.PtrTo(true),
},
},
})
curl -X PATCH "https://video.stream-io-api.com/api/v2/video/call/default/${CALL_ID}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings_override": {
"audio": {
"mic_default_on": true,
"default_device": "speaker"
}
}
}'
Manage call members
You can provide a list of call members, this can be done when you create a call or later on when the call already exists. Please note that call members need to be existing users.
There are two reasons to use call members:
- Call membership allows you to have more flexibility when it comes to permissions. The permission system allows you to grant different permissions to users and members, this way one user can be a member on one call or a member on another. Membership also allows you to grant additional roles to users in a call. It’s important to note that this doesn’t restrict access, but rather expands capabilities. You can more information about the roles and permissions here.
- Call members will receive push notifications.
// Call members need to be existing users
call.updateCallMembers({
// You can add new members
// You can also update the role of existing members
update_members: [{ user_id: "sara" }, { user_id: "emily", role: "admin" }],
});
# Call members need to be existing users
# You can also update the role of existing members
call.update_call_members(
update_members=[
MemberRequest(user_id="sara"),
MemberRequest(user_id="emily", role="admin"),
]
)
// Call members need to be existing users (use `client.UpdateUsers` for that)
// You can also update the role of existing members
response, err := call.UpdateCallMembers(ctx, &getstream.UpdateCallMembersRequest{
UpdateMembers: []getstream.MemberRequest{
{UserID: "sara"},
{UserID: "emily", Role: getstream.PtrTo("admin")},
},
})
# You can only add existing members to a call
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${CALL_TYPE}/${CALL_ID}/members?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "Content-Type: application/json" \
-H "stream-auth-type: jwt" \
-d '{
"update_members": [
{ "user_id": "sara" },
{ "user_id": "john", "role": "admin" }
]
}'
You can also remove call members:
call.updateCallMembers({
remove_members: ["sara"],
});
call.update_call_members(remove_members=["sara"])
response, err := call.UpdateCallMembers(ctx, &getstream.UpdateCallMembersRequest{
RemoveMembers: []string{
"sara",
},
})
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${CALL_TYPE}/${CALL_ID}/members?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "Content-Type: application/json" \
-H "stream-auth-type: jwt" \
-d '{
"remove_members": ["sara"]
}'
Restrict call access
You can restrict access to a call by updating the Call Type permissions and roles. A typical use case is to restrict access to a call to a specific set of users -> call members.
By default, all users unless specified otherwise, have the user
role.
You can remove the join-call
permission from the user
role for the given call type scope. This will prevent regular users from joining a call of the given type.
Next, let’s ensure that the call_member
role has the join-call
permission for the given call type scope. This will allow users with the call_member
role to join a call of this type.
Once this is set, we can proceed with setting up a call
instance and providing the members
.
const callTypeName = "default";
const callType = (await client.video.listCallTypes()).call_types[callTypeName];
// Remove JOIN_CALL permission from user role
const userGrants = callType.grants["user"].filter(
(c) => c !== OwnCapability.JOIN_CALL,
);
// Make sure JOIN_CALL permission is set for call_member role
const callMemberGrants = callType.grants["call_member"];
if (!callMemberGrants.includes(OwnCapability.JOIN_CALL)) {
callMemberGrants.push(OwnCapability.JOIN_CALL);
}
// Update the call type with the changes
await client.video.updateCallType({
name: callTypeName,
grants: {
user: userGrants,
call_member: callMemberGrants,
},
});
response = client.video.update_call_type(
name="default",
grants={
"user": [],
"call_member": [
OwnCapability.READ_CALL,
OwnCapability.SEND_VIDEO,
OwnCapability.SEND_AUDIO,
OwnCapability.JOIN_CALL,
],
},
)
response, err := client.Video().UpdateCallType(ctx, "default", &getstream.UpdateCallTypeRequest{
Grants: &map[string][]string{
"user": []string{},
"call_member": []string{
READ_CALL.String(),
SEND_VIDEO.String(),
SEND_AUDIO.String(),
JOIN_CALL.String(),
},
},
})
# Remove join call grant from user role, only include this for call_member role
curl -X PUT "https://video.stream-io-api.com/api/v2/video/calltypes/${CALL_TYPE_NAME}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "Content-Type: application/json" \
-H "stream-auth-type: jwt" \
-d '{
"grants": {
"user": [...list all grants for user here],
"call_member": [...list all grants for call member here, "join-call"]
}
}'
Sessions
Call IDs can be reused, which means a call can be joined and left by participants multiple times. Every time the first participant joins the call, a new session is started. Every time the last participant left the call, the session is ended.
If a call session is started, the
call.session_started
WebSocket event will be dispatched. It’s also possible to send push notifications to call members on this event, for more information see the Call Types page.If a call session is ended, the
call.session_ended
WebSocket event will be dispatched.
Ending calls
This action terminates the call for everyone. Ending a call requires the end-call
permission.
await call.end();
call.end()
call.End(ctx, &getstream.EndCallRequest{})
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${CALL_TYPE}/${CALL_ID}/mark_ended?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt"
Only users with the join-ended-call
permission can join an ended call.
Query calls
For many video calling, live stream, or audio rooms apps, you’ll want to show:
- Upcoming calls
- Calls that are currently live
- Popular live streams / audio rooms with a link to the recording
Examples
Below you can find a few examples of different queries:
Sorting and pagination
// default sorting
client.video.queryCalls();
// sorting and pagination
const queryCallsReq = {
sort: [{ field: "starts_at", direction: -1 }],
limit: 2,
};
response = await client.video.queryCalls(queryCallsReq);
// loading next page
client.video.queryCalls({
...queryCallsReq,
next: response.next,
});
# default sorting
client.query_calls()
# sorting and pagination
response = client.query_calls(
sort= [SortParamRequest(field: 'starts_at', direction: -1)],
limit=2,
)
# loading next page
client.query_calls(
sort= [SortParamRequest(field: 'starts_at', direction: -1)],
limit=2,
next=response.data().next
)
// default sorting
client.Video().QueryCalls(ctx, &getstream.QueryCallsRequest{})
// sorting and pagination
response, err := client.Video().QueryCalls(ctx, &getstream.QueryCallsRequest{
Sort: []*getstream.SortParamRequest{&getstream.SortParamRequest{
Field: getstream.PtrTo("starts_at"),
Direction: getstream.PtrTo(-1),
}
},
Limit: getstream.PtrTo(2),
},
)
// loading next page
client.Video().QueryCalls(ctx, &getstream.QueryCallsRequest{
Sort: []*getstream.SortParamRequest{&getstream.SortParamRequest{
Field: getstream.PtrTo("starts_at"),
Direction: getstream.PtrTo(-1),
}
},
Limit: getstream.PtrTo(2),
Next: response.Data.Next,
})
curl -X POST "https://video.stream-io-api.com/api/v2/video/calls?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{ "sort": [{ "field": "starts_at", "direction": -1 }], "limit": 2 }'
# Loading next page
curl -X POST "https://video.stream-io-api.com/api/v2/video/calls?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{ "sort": [{ "field": "starts_at", "direction": -1 }], "limit": 2, "next": "<pointer from previous response>" }'
Query live calls
client.video.queryCalls({
filter_conditions: { backstage: { $eq: false } },
});
client.video.query_calls(
filter_conditions={'backstage': {'$eq': False}}
)
client.Video().QueryCalls(ctx, &getstream.QueryCallsRequest{
FilterConditions: &map[string]interface{}{
"backstage": false,
},
})
curl -X POST "https://video.stream-io-api.com/api/v2/video/calls?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{ "filter_conditions": { "backstage": { "$eq": false } } }'
Query upcoming calls
const mins30 = 1000 * 60 * 30;
const inNext30mins = new Date(Date.now() + mins30);
client.video.queryCalls({
filter_conditions: {
starts_at: { $gt: inNext30mins.toISOString() },
},
});
from datetime import datetime, timedelta
min30s = timedelta(minutes=30)
in_next_30_mins = datetime.now() + min30s
client.video.query_calls(
filter_conditions={'starts_at': {'$gt': in_next_30_mins.isoformat()}}
)
// in next 30 minutes
inNext30Mins := time.Now().Add(30 * time.Minute)
client.Video().QueryCalls(ctx, &getstream.QueryCallsRequest{
FilterConditions: &map[string]interface{}{
"starts_at": inNext30Mins.Format(time.RFC3339),
},
})
# Provide the time in ISO date string
curl -X POST "https://video.stream-io-api.com/api/v2/video/calls?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{ "filter_conditions": { "starts_at": { "$gt": "2024-05-10T09:09:03.584Z" } } }'
Query ongoing calls
client.video.queryCalls({
filter_conditions: { ongoing: { $eq: true } },
});
client.video.query_calls(
filter_conditions={'ongoing': {'$eq': True}}
)
client.Video().QueryCalls(ctx, &getstream.QueryCallsRequest{
FilterConditions: &map[string]interface{}{
"ongoing": true,
},
})
curl -X POST "https://video.stream-io-api.com/api/v2/video/calls?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"filter_conditions": { "ongoing": { "$eq": true } }
}'
Sort options
Sorting is supported on these fields:
starts_at
created_at
updated_at
ended_at
type
id
cid
Filter options
Name | Type | Description | Supported operators |
---|---|---|---|
id | string | Call ID | $in , $eq , $gt, $gte , $lt , $lte , $exists |
cid | string | Call CID (format: type:id) | $in , $eq , $gt, $gte , $lt , $lte , $exists |
team | string | The team associated with the channel | $in , $eq , $gt, $gte , $lt , $lte , $exists |
type | string | Call type | $in , $eq , $gt, $gte , $lt , $lte , $exists |
created_by_user_id | string | User ID of the call’s creator | $in , $eq , $gt, $gte , $lt , $lte , $exists |
created_at | string, must be formatted as an RFC3339 timestamp (for example 2021-01-15T09:30:20.45Z) | Creation time of the call | $in , $eq , $gt, $gte , $lt , $lte , $exists |
updated_at | string, must be formatted as an RFC3339 timestamp (for example 2021-01-15T09:30:20.45Z) | The time of the last update of the call | $in , $eq , $gt, $gte , $lt , $lte , $exists |
ended_at | string, must be formatted as an RFC3339 timestamp (for example 2021-01-15T09:30:20.45Z) | The time the call was ended | $in , $eq , $gt, $gte , $lt , $lte , $exists |
starts_at | string, must be formatted as an RFC3339 timestamp (for example 2021-01-15T09:30:20.45Z) | The scheduled start time of the call | $in , $eq , $gt, $gte , $lt , $lte , $exists |
backstage | boolean | true if the call is in backstage mode | $eq |
members | string array | Member user ids | $in |
ongoing | boolean | true if there is an ongoing session for the call | $eq |
The Stream API allows you to specify filters and ordering for several endpoints. The query syntax is similar to that of Mongoose, however we do not run MongoDB on the backend. Only a subset of the MongoDB operations are supported.
Name | Description | Example |
---|---|---|
$eq | Matches values that are equal to a specified value. | { "key": { "$eq": "value" } } or the simplest form { "key": "value" } |
$q | Full text search (matches values where the whole text value matches the specified value) | { "key": { "$q": "value } } |
$gt | Matches values that are greater than a specified value. | { "key": { "$gt": 4 } } |
$gte | Matches values that are greater than or equal to a specified value. | { "key": { "$gte": 4 } } |
$lt | Matches values that are less than a specified value. | { "key": { "$lt": 4 } } |
$lte | Matches values that are less than or equal to a specified value. | { "key": { "$lte": 4 } } |
$in | Matches any of the values specified in an array. | { "key": { "$in": [ 1, 2, 4 ] } } |
$exists | Mathces values that either have (when set to true ) or not have (when set to false ) certain attributes | { "key": { "$exists": true } } |
$autocomplete | Mathces values that start with the specified string value | { "key": { "$autocomplete": "value" } } |
It’s also possible to combine filter expressions with the following operators:
Name | Description | Example |
---|---|---|
$and | Matches all the values specified in an array. | { "$and": [ { "key": { "$in": [ 1, 2, 4 ] } }, { "some_other_key": 10 } ] } |
$or | Matches at least one of the values specified in an array. | { "$or": [ { "key": { "$in": [ 1, 2, 4 ] } }, { "key2": 10 } ] } |
Query call members
// default sorting
call.queryMembers();
// sorting and pagination
const queryMembersReq = {
sort: [{ field: "user_id", direction: 1 }],
limit: 2,
};
const response = await call.queryMembers({ payload: queryMembersReq });
// loading next page
call.queryMembers({
payload: {
...queryMembersReq,
next: response.next,
},
});
// filtering
call.queryMembers({
payload: { filter_conditions: { role: { $eq: "admin" } } },
});
# default sorting
call.query_members()
# sorting and pagination
response = call.query_members(
sort: [SortParamRequest(field: "user_id", direction: 1)],
limit: 2,
)
# loading next page
call.query_members(
sort: [SortParamRequest(field: "user_id", direction: 1)],
limit: 2,
next: response.next,
)
# filtering
call.query_members(
filter_conditions: {"role": {"$eq": "admin"}},
)
// default sorting
client.Video().QueryCallMembers(ctx, &getstream.QueryCallMembersRequest{})
// sorting and pagination
response, err := client.Video().QueryCallMembers(ctx, &getstream.QueryCallMembersRequest{
Sort: []*getstream.SortParamRequest{&getstream.SortParamRequest{
Field: getstream.PtrTo("user_id"),
Direction: getstream.PtrTo(1),
},
},
Limit: getstream.PtrTo(2),
},
)
// loading next page
client.Video().QueryCallMembers(ctx, &getstream.QueryCallMembersRequest{
Sort: []*getstream.SortParamRequest{&getstream.SortParamRequest{
Field: getstream.PtrTo("user_id"),
Direction: getstream.PtrTo(1),
},
},
Limit: getstream.PtrTo(2),
Next: response.Data.Next,
})
// filtering
client.Video().QueryCallMembers(ctx, &getstream.QueryCallMembersRequest{
FilterConditions: &map[string]interface{}{
"role": "admin",
},
})
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/members?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"id": "'${CALL_ID}'",
"type": "'${CALL_TYPE}'"
}'
# Sorting and pagination
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/members?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"id": "'${CALL_ID}'",
"type": "'${CALL_TYPE}'",
"sort": [{ "field": "user_id", "direction": 1 }],
"limit": 2
}'
# Load next page
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/members?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"id": "'${CALL_ID}'",
"type": "'${CALL_TYPE}'",
"sort": [{ "field": "user_id", "direction": 1 }],
"limit": 2,
"next": "<pointer to next page>"
}'
# Filtering
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/members?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"id": "'${CALL_ID}'",
"type": "'${CALL_TYPE}'",
"filter_conditions": { "role": { "$eq": "admin" } }
}'
Sort options
Sorting is supported on these fields:
user_id
created_at
Filter options
Name | Type | Description | Supported operators |
---|---|---|---|
user_id | string | User ID | $in , $eq , $gt, $gte , $lt , $lte , $exists |
role | string | The role of the user | $in , $eq , $gt, $gte , $lt , $lte , $exists |
custom | Object | Search in custom membership data, example syntax: {'custom.color': {$eq: 'red'}} | $in , $eq , $gt, $gte , $lt , $lte , $exists |
created_at | string, must be formatted as an RFC3339 timestamp (for example 2021-01-15T09:30:20.45Z) | Creation time of the user | $in , $eq , $gt, $gte , $lt , $lte , $exists |
updated_at | string, must be formatted as an RFC3339 timestamp (for example 2021-01-15T09:30:20.45Z) | The time of the last update of the user | $in , $eq , $gt, $gte , $lt , $lte , $exists |
The Stream API allows you to specify filters and ordering for several endpoints. The query syntax is similar to that of Mongoose, however we do not run MongoDB on the backend. Only a subset of the MongoDB operations are supported.
Name | Description | Example |
---|---|---|
$eq | Matches values that are equal to a specified value. | { "key": { "$eq": "value" } } or the simplest form { "key": "value" } |
$q | Full text search (matches values where the whole text value matches the specified value) | { "key": { "$q": "value } } |
$gt | Matches values that are greater than a specified value. | { "key": { "$gt": 4 } } |
$gte | Matches values that are greater than or equal to a specified value. | { "key": { "$gte": 4 } } |
$lt | Matches values that are less than a specified value. | { "key": { "$lt": 4 } } |
$lte | Matches values that are less than or equal to a specified value. | { "key": { "$lte": 4 } } |
$in | Matches any of the values specified in an array. | { "key": { "$in": [ 1, 2, 4 ] } } |
$exists | Mathces values that either have (when set to true ) or not have (when set to false ) certain attributes | { "key": { "$exists": true } } |
$autocomplete | Mathces values that start with the specified string value | { "key": { "$autocomplete": "value" } } |
It’s also possible to combine filter expressions with the following operators:
Name | Description | Example |
---|---|---|
$and | Matches all the values specified in an array. | { "$and": [ { "key": { "$in": [ 1, 2, 4 ] } }, { "some_other_key": 10 } ] } |
$or | Matches at least one of the values specified in an array. | { "$or": [ { "key": { "$in": [ 1, 2, 4 ] } }, { "key2": 10 } ] } |
Send custom event
It’s possible to send any custom event for a call:
// send a custom event to all users watching the call
call.sendCallEvent({
custom: {
"render-animation": "balloons",
},
user_id: "john",
});
# send a custom event to all users watching the call
call.send_call_event(user_id=user.id, custom={"render-animation": "balloons"})
// send a custom event to all users watching the call
call.SendCallEvent(ctx, &getstream.SendCallEventRequest{
Custom: &map[string]interface{}{
"render-animation": "balloons",
},
UserID: PtrTo("john"),
})
curl -X POST https://video.stream-io-api.com/api/v2/video/call/${CALL_TYPE}/${CALL_ID}/event?api_key=${API_KEY} \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H 'Content-Type: application/json' \
-d '{
"custom": {"render-animation": "balloons"},
"user_id": "john"
}'
Sending a custom event will dispatch the custom
WebSocket event.
Pin and unpin video
You can pin the video of a participant in a call session. The SDKs will make sure that the pinned participant is displayed in a prominent location in the call layout for all participants. You can also unpin a pinned participant if you no longer want to highlight them.
await call.videoPin({
session_id: "session-id",
user_id: "user-id-to-pin",
});
await call.videoUnpin({
session_id: "session-id",
user_id: "user-id-to-unpin",
});
# Pin video for all participants
call.video_pin(session_id="session-id", user_id="user-id-to-pin")
# Unpin video for all participants
call.video_unpin(session_id="session-id", user_id="user-id-to-unpin")
// Pin video for all participants
call.VideoPin(ctx, &getstream.PinRequest{
SessionID: "session-id",
UserID: "user-id-to-pin",
})
// Unpin video for all participants
call.VideoUnpin(ctx, &getstream.UnpinRequest{
SessionID: "session-id",
UserID: "user-id-to-unpin",
})
# Pin video
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${CALL_TYPE}/${CALL_ID}/pin?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"session_id": "session-id",
"user_id": "user-id-to-pin"
}'
# Unpin video
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${CALL_TYPE}/${CALL_ID}/unpin?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"session_id": "session-id",
"user_id": "user-id-to-unpin"
}'
Session Timers
You can limit the maximum duration for calls. This limit can be set for individual calls or set to a default value for all calls with the same type. When set, users will be automatically removed from a call when the time runs out and the call will be marked as ended.
Please note that by default, most call types are configured so that users can join ended calls. To ensure session timers work correctly, the JoinEndedCall
permission should be disabled at the call level. This can be done from the dashboard.
Call type configuration
You can configure all calls to have a default max duration, this can be done from the Dashboard (Call Type Settings) or using the API.
await client.video.updateCallType({
name: "default",
settings: {
limits: {
max_duration_seconds: 3600,
},
},
});
// Disable the default session timer
await client.video.updateCallType({
name: "default",
settings: {
limits: {
max_duration_seconds: 0,
},
},
});
from getstream.models import CallSettingsRequest, LimitsSettingsRequest
# Set default max duration to 1 hour
client.video.update_call_type(
"default",
settings=CallSettingsRequest(
limits=LimitsSettingsRequest(
max_duration_seconds=3600,
),
),
)
# Disable the default session timer
client.video.update_call_type(
"default",
settings=CallSettingsRequest(
limits=LimitsSettingsRequest(
max_duration_seconds=0,
),
),
)
// Set default max duration to 1 hour
client.Video().UpdateCallType(ctx, "default", &getstream.UpdateCallTypeRequest{
Settings: &CallSettingsRequest{
Limits: &LimitsSettingsRequest{
MaxDurationSeconds: getstream.PtrTo(3600),
},
},
})
// Disable the default session timer
client.Video().UpdateCallType(ctx, "default", &getstream.UpdateCallTypeRequest{
Settings: &getstream.CallSettingsRequest{
Limits: &getstream.LimitsSettingsRequest{
MaxDurationSeconds: getstream.PtrTo(0),
},
},
})
curl -X PUT "https://video.stream-io-api.com/api/v2/video/calltypes/${CALL_TYPE_NAME}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings": {
"limits": {
"max_duration_seconds": 3600,
}
}
}'
# Disable the default session timer
curl -X PUT "https://video.stream-io-api.com/api/v2/video/calltypes/${CALL_TYPE_NAME}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings": {
"limits": {
"max_duration_seconds": 0,
}
}
}'
Create call with session timer
It is possible to create calls with a different max duration than the default defined at the call type.
// or call.create
await client.call("default", "test-outgoing-call").getOrCreate({
data: {
created_by_id: "john",
settings_override: {
limits: {
max_duration_seconds: 3600,
},
},
},
});
from getstream.models import CallRequest, CallSettingsRequest, LimitsSettingsRequest
call.get_or_create(
data=CallRequest(
created_by_id="john",
settings_override=CallSettingsRequest(
limits=LimitsSettingsRequest(
max_duration_seconds=3600,
),
),
)
)
call.GetOrCreate(ctx, &getstream.GetOrCreateCallRequest{
Data: &getstream.CallRequest{
CreatedByID: getstream.PtrTo("john"),
SettingsOverride: &getstream.CallSettingsRequest{
Limits: &getstream.LimitsSettingsRequest{
MaxDurationSeconds: getstream.PtrTo(3600),
},
},
},
})
# Creates a call with session timer
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${CALL_TYPE}/${CALL_ID}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "Content-Type: application/json" \
-H "stream-auth-type: jwt" \
-d '{
"data": {
"created_by_id": "john",
"settings_override": {
"limits": {
"max_duration_seconds": 3600
},
}
}
}'
Updating call object to extend session time
It is possible to update a call and extend the session time. In that case a call.updated
event is sent to all connected clients so that their UI can be updated accordingly.
// Update the call with session timer
await client.call.update({
data: {
settings_override: {
limits: {
max_duration_seconds: call.settings.limits.max_duration_seconds + 300,
},
},
},
});
// Disable the session timer
await client.call.update({
data: {
settings_override: {
limits: {
max_duration_seconds: 0,
},
},
},
});
from getstream.models import CallSettingsRequest, LimitsSettingsRequest
# Updates a call with session timer
call.update(
settings_override=CallSettingsRequest(
limits=LimitsSettingsRequest(
max_duration_seconds=3600,
),
),
)
# Disable the session timer
call.update(
settings_override=CallSettingsRequest(
limits=LimitsSettingsRequest(
max_duration_seconds=0,
),
),
)
// Updates a call with session timer
call.Update(ctx, &getstream.UpdateCallRequest{
SettingsOverride: &getstream.CallSettingsRequest{
Limits: &getstream.LimitsSettingsRequest{
MaxDurationSeconds: getstream.PtrTo(3600),
},
},
})
// Disable the session timer
call.Update(ctx, &getstream.UpdateCallRequest{
SettingsOverride: &getstream.CallSettingsRequest{
Limits: &getstream.LimitsSettingsRequest{
MaxDurationSeconds: getstream.PtrTo(0),
},
},
})
# Updates a call with session timer
curl -X PATCH "https://video.stream-io-api.com/api/v2/video/call/default/${CALL_ID}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings_override": {
"limits": {
"max_duration_seconds": 3600,
}
}
}'
# Disable the session timer
curl -X PATCH "https://video.stream-io-api.com/api/v2/video/call/default/${CALL_ID}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings_override": {
"limits": {
"max_duration_seconds": 0,
}
}
}'