Get started
Stream powers Chat Messaging, Video & Audio, and Activity Feeds for billions of global end-users across thousands of different apps.
Stream’s global edge network ensures a faster and more reliable experience for your video calls and livestreams. Excellent developer experience and docs enable you to build in-app video calling in days. Scale to millions of users and thousands of call participants.
For the average Stream integration, the development work focuses on code that executes in the client. However, some tasks must be executed from the server for safety (for example, token generation).
Stream provides server-side SDKs to help execute these tasks.
You can reference our development roadmap to know which languages and features are supported.
Installation
All official SDKs are available on package managers, full source code is available on the GetStream Github organization.
- Python
- JavaScript
- Golang
pip install getstream
npm install @stream-io/node-sdk
// or using yarn
yarn add @stream-io/node-sdk
go get github.com/GetStream/getstream-go
The source code of our SDKs is available on Github. If you find issues with any SDK you can also create an issue on Github directly:
Creating client
To create a server-side client, you'll need your API key and secret. Both of them can be found in your Stream Dashboard.
You can optionally pass a timeout for the API requests, the default timeout is 3000ms.
- Python
- JavaScript
- Golang
- Bash
from getstream import Stream
client = Stream(api_key="your_api_key", api_secret="your_api_secret", timeout=3.0)
import { StreamClient } from '@stream-io/node-sdk';
// or
// const { StreamClient } = require("@stream-io/node-sdk");
const apiKey = '';
const secret = '';
client = new StreamClient(apiKey, secret);
// optionally add timeout to API requests
// the default timeout is 3000ms
client = new StreamClient(apiKey, secret, { timeout: 3000 });
import "github.com/GetStream/getstream-go"
client, err := getstream.NewClient(
apiKey,
apiSecret,
getstream.WithTimeout(10_000*time.Millisecond),
)
# Create a server token
HEADER=$(echo -n '{"alg": "HS256", "typ": "JWT"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=');
PAYLOAD=$(echo -n '{"server": true}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=');
SECRET='<API secret>';
SIGNATURE=$(echo -n ${HEADER}.${PAYLOAD} | openssl dgst -sha256 -hmac ${SECRET} -binary | openssl base64 -e -A | tr '+/' '-_' | tr -d '=');
TOKEN="${HEADER}.${PAYLOAD}.${SIGNATURE}";
API_KEY='<API key>';
# Provide API key, token and auth header to all requests
curl -X GET "https://video.stream-io-api.com/api/v2/app?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt"
Creating users and user tokens
To create a user you need to provide an ID, and their role. Optionally you can also specify their name and an image, these fields are recognized and rendered by the default SDK components. It's also possible to add any other custom data.
Tokens need to be generated server-side. Typically, you integrate this into the part of your codebase where you log in or register users. The tokens provide a way to authenticate a user or give access to a specific set of video/audio calls.
- JavaScript
- Python
- Golang
- cURL
const userId = 'john';
const newUser: UserRequest = {
id: userId,
role: 'user',
custom: {
color: 'red',
},
name: 'John',
image: 'link/to/profile/image',
};
await client.upsertUsers([newUser]);
// validity is optional (by default the token is valid for an hour)
const vailidity = 60 * 60;
client.generateUserToken({ user_id: userId, validity_in_seconds: validity });
from getstream.models import UserRequest
# ensure the user exists
client.upsert_users(
UserRequest(
id="tommaso-id", name="tommaso", role="admin", custom={"country": "NL"}
),
)
# the token will be valid for 1 hour
client.create_token(user_id="tommaso-id", expiration=3600)
// optional values are passed as pointers, you can use `getstream.PtrTo`
// to get pointers from literals of any type
response, err := client.UpdateUsers(ctx, &getstream.UpdateUsersRequest{
Users: map[string]getstream.UserRequest{
"user-id": {
ID: "user-id",
Name: getstream.PtrTo("tommaso"),
Custom: map[string]any{"country": "NL"},
},
},
})
// create a user token valid for 24 hours
token, err := client.CreateToken("tommaso-id", getstream.WithExpiration(24*time.Hour))
curl -X POST https://video.stream-io-api.com/api/v2/users?api_key=${API_KEY} \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"users": {
"john": {
"id": "john",
"role": "user",
"custom": {
"color": "red"
},
"name": "John",
"image": "link/to/profile/image"
}
}
}'
Creating a call
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.
- JavaScript
- Python
- Golang
- cURL
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: /* */});
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" }
}
}'
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.
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.
- JavaScript
- Python
- Golang
- cURL
// 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:
- JavaScript
- Python
- Golang
- cURL
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"]
}'
Updating a call
Default call settings are inherited from the call type. These settings can be overridden if necessary.
- JavaScript
- Python
- Golang
- cURL
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"
}
}
}'