curl --request POST \
--url https://api.staging.glot.com/v1/rooms/{room_id}/invites \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"expires_in_seconds": 3600,
"max_uses": 1
}
'import requests
url = "https://api.staging.glot.com/v1/rooms/{room_id}/invites"
payload = {
"expires_in_seconds": 3600,
"max_uses": 1
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({expires_in_seconds: 3600, max_uses: 1})
};
fetch('https://api.staging.glot.com/v1/rooms/{room_id}/invites', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.staging.glot.com/v1/rooms/{room_id}/invites",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'expires_in_seconds' => 3600,
'max_uses' => 1
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.staging.glot.com/v1/rooms/{room_id}/invites"
payload := strings.NewReader("{\n \"expires_in_seconds\": 3600,\n \"max_uses\": 1\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.staging.glot.com/v1/rooms/{room_id}/invites")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"expires_in_seconds\": 3600,\n \"max_uses\": 1\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.staging.glot.com/v1/rooms/{room_id}/invites")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"expires_in_seconds\": 3600,\n \"max_uses\": 1\n}"
response = http.request(request)
puts response.read_body{
"invite_code": "<string>",
"expires_at": "2023-11-07T05:31:56Z",
"max_uses": 123
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Create an invite link
Mint a link that lets someone without an account join this room.
The way a guest gets in. Everyone else needs a token from
POST /v1/rooms/{room_name}/token, which only an authenticated member of your
organization can request — this hands out a single-purpose capability instead, so a
guest-facing page never needs your credentials. Send the code to your guest in a link
to your own page; that page reads the room with GET /v1/invites/{invite_code} and
joins through POST /v1/invites/{invite_code}/join.
The code is returned once, here. Only a hash of it is stored, so no endpoint can read it back. Lose it and you revoke the link and mint another.
Works in a room of either streaming mode, and minting neither sets nor changes it.
What the mode decides is how many languages your guest sends when they join — one in a
dual room, two in a mono one, where a single device carries both speakers.
GET /v1/invites/{invite_code} reports that count as languages_required, so the page
you send them can render the right chooser. If the room has no mode yet, your guest’s
join may be the token that settles it, exactly as POST /v1/rooms/{room_name}/token
would.
expires_in_seconds and max_uses are both required — together with revocation they
are the only things bounding a link once you have sent it, so they are yours to choose,
up to a ceiling of 30 days and 100 uses. A link is unusable the moment either runs out,
and returns 410 from then on.
Anything but a live room in your organization returns 404.
curl --request POST \
--url https://api.staging.glot.com/v1/rooms/{room_id}/invites \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"expires_in_seconds": 3600,
"max_uses": 1
}
'import requests
url = "https://api.staging.glot.com/v1/rooms/{room_id}/invites"
payload = {
"expires_in_seconds": 3600,
"max_uses": 1
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({expires_in_seconds: 3600, max_uses: 1})
};
fetch('https://api.staging.glot.com/v1/rooms/{room_id}/invites', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.staging.glot.com/v1/rooms/{room_id}/invites",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'expires_in_seconds' => 3600,
'max_uses' => 1
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.staging.glot.com/v1/rooms/{room_id}/invites"
payload := strings.NewReader("{\n \"expires_in_seconds\": 3600,\n \"max_uses\": 1\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.staging.glot.com/v1/rooms/{room_id}/invites")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"expires_in_seconds\": 3600,\n \"max_uses\": 1\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.staging.glot.com/v1/rooms/{room_id}/invites")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"expires_in_seconds\": 3600,\n \"max_uses\": 1\n}"
response = http.request(request)
puts response.read_body{
"invite_code": "<string>",
"expires_at": "2023-11-07T05:31:56Z",
"max_uses": 123
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Path Parameters
Body
Mint an invite link for a room, bounded in time and in uses.
Both fields are required: how long a shareable credential lives, and how many guests
it lets in, are the only two things that bound a link once it leaves your hands, so
they are yours to state rather than ours to default. A leaked link is bounded by
exactly what you asked for here — and by DELETE /v1/rooms/{room_id}/invites, which
retires the room's links at once and takes effect immediately.
Each field also has a server-side ceiling (30 days, 100 uses). They are not a policy about how you should run your calls — they are the outer edge of what a single unauthenticated bearer capability may be, and they are what keeps an out-of-range value a 422 naming the bound instead of a number the database cannot hold. If you need more than either allows, mint another link.
How long the link stays usable, in seconds from now, counted on the server's clock. Required — there is no default, because a link that outlives the conversation it was for is the one mistake this field exists to prevent. After it passes, the link returns 410 and cannot be renewed; mint a new one.
At most 30 days (2,592,000). A shareable credential nobody has to re-authorize should not outlive the quarter it was made in, and the cap is also what stops a value large enough to overflow the stored timestamp from reaching the database at all.
60 <= x <= 25920003600
How many times this link may be redeemed. Required, and there is no unlimited option. Send 1 for a link meant for one guest — the common case, and the one where a forwarded link cannot let a stranger in behind them. A higher number admits that many separate guests.
This bounds the link, not the room: a room itself has no participant limit, so mint a link with the number of uses you actually intend to hand out, or several links, as suits you. The room's only limit is that everyone in it must be speaking at most two languages between them.
At most 100. One link admitting an unbounded crowd is a different kind of credential from the one this endpoint issues; mint several if you need to hand out more, so that a single leak costs you at most one of them.
1 <= x <= 1001
Response
Successful Response
A minted invite link.
invite_code is shown here and nowhere else. Only a hash of it is stored, so it
cannot be read back from any endpoint — put it in the link you send your guest, and
save it if you will need it again. Losing it costs you nothing you cannot undo:
DELETE /v1/rooms/{room_id}/invites retires the room's links without it.
Build the guest's URL yourself, pointing at your own page: that page reads the room's
state from GET /v1/invites/{invite_code} and joins through
POST /v1/invites/{invite_code}/join. Keep the code in the URL's path, not its
query string, so it does not travel to third parties in a Referer header.