Meet API Docs Dashboard
On this page

Create Meeting Tokens on Your Server

Your server holds the secret key. It makes the room, then one token for each person who joins.

Every example reads the key from the environment, makes a private room with a name Meet generates, and mints a host token valid for one hour. Set the key first:

bash
export MEET_API_KEY=mk_test_xxxxxxxx

Never put the key in a web page, a mobile app or a repository. Give the browser only the token.

Publishing. The SDK packages are not on npm, PyPI, Packagist or the Go module proxy yet. Until they are, the REST API works from any language over plain HTTPS: every REST reference page has a curl example.

Node#

bash
npm i @respiresoft/meet
js
// token.mjs  (Node 18 or newer)
import { Meet } from "@respiresoft/meet";

const meet = new Meet({ apiKey: process.env.MEET_API_KEY });
const room = await meet.rooms.create({ privacy: "private" });
const { token, url } = await meet.rooms.createToken(room.name, {
  user_id: "u-77", name: "Ann", role: "host", ttl: 3600,
});
console.log(room.name, url);   // send `token` and `room.url` to the browser

Run it with node token.mjs. The SDK retries on 429 and 5xx, and adds an Idempotency-Key to every POST. Details are in the Node SDK page.

Python#

bash
pip install respiresoft-meet
python
# token.py  (Python 3.10 or newer)
import os
from respiresoft_meet import Meet

meet = Meet(api_key=os.environ["MEET_API_KEY"])
room = meet.rooms.create(privacy="private")
result = meet.rooms.create_token(room["name"], user_id="u-77", user_name="Ann", role="host", ttl=3600)
print(room["name"], result["url"])   # send result["token"] and room["url"] to the browser

PHP#

No package is needed. This uses the cURL extension that ships with PHP.

php
<?php
// token.php  (PHP 8 with ext-curl)
function meet(string $method, string $path, ?array $body = null): array {
    $ch = curl_init("https://meet.respiresoft.com" . $path);
    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST => $method,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            "Authorization: Bearer " . getenv("MEET_API_KEY"),
            "Content-Type: application/json",
            "Idempotency-Key: " . bin2hex(random_bytes(16)),
        ],
        CURLOPT_POSTFIELDS => $body === null ? null : json_encode($body),
        CURLOPT_TIMEOUT => 15,
    ]);
    $raw = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);
    $data = json_decode((string) $raw, true) ?? [];
    if ($status >= 400) {
        throw new RuntimeException(($data["error"]["code"] ?? "error") . ": " . ($data["error"]["message"] ?? $status));
    }
    return $data;
}

$room = meet("POST", "/api/v1/rooms", ["privacy" => "private"]);
$token = meet("POST", "/api/v1/rooms/" . rawurlencode($room["name"]) . "/tokens",
    ["user_id" => "u-77", "name" => "Ann", "role" => "host", "ttl" => 3600]);
echo $room["name"], " ", $token["url"], "\n";

Go#

No package is needed. This uses the standard library.

go
// token.go  (Go 1.21 or newer)
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"time"
)

var client = &http.Client{Timeout: 15 * time.Second}

func meet(method, path string, body any, out any) error {
	var rd *bytes.Reader
	if body != nil {
		b, _ := json.Marshal(body)
		rd = bytes.NewReader(b)
	} else {
		rd = bytes.NewReader(nil)
	}
	req, _ := http.NewRequest(method, "https://meet.respiresoft.com"+path, rd)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("MEET_API_KEY"))
	req.Header.Set("Content-Type", "application/json")
	res, err := client.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if res.StatusCode >= 400 {
		var e struct{ Error struct{ Code, Message string } }
		json.NewDecoder(res.Body).Decode(&e)
		return fmt.Errorf("%d %s: %s", res.StatusCode, e.Error.Code, e.Error.Message)
	}
	return json.NewDecoder(res.Body).Decode(out)
}

func main() {
	var room struct{ Name, URL string }
	if err := meet("POST", "/api/v1/rooms", map[string]any{"privacy": "private"}, &room); err != nil {
		panic(err)
	}
	var tok struct{ Token, URL string }
	err := meet("POST", "/api/v1/rooms/"+url.PathEscape(room.Name)+"/tokens",
		map[string]any{"user_id": "u-77", "name": "Ann", "role": "host", "ttl": 3600}, &tok)
	if err != nil {
		panic(err)
	}
	fmt.Println(room.Name, tok.URL)
}

Run it with go run token.go. Go decodes JSON keys without regard to case, so Name, URL and Token match name, url and token.

What to do with the token#

Send token (and the room's url) to the browser of that one person, then pass them to Meet.embed or add ?token= to the room link. A token works in one room only. Mint a new one each time a person opens the meeting. Read Meeting tokens for the roles and permissions you can set.

Errors you may meet#

Status and code What to do
401 invalid_api_key The key is wrong or revoked. Make a new one in the dashboard.
409 room_exists Room names are unique across Meet. Leave name out to get a generated one.
429 rate_limited Wait the Retry-After seconds. The limit is 120 requests a minute for each key.

The full list is in Errors.