Announcing self-signed meeting tokens

At Daily we are big believers in building on top of open standards. Our core offering is built on top of WebRTC, which is now officially a standard 🎉. So, it may not surprise you to know that, under the hood, our meeting tokens are just JSON Web Tokens (JWTs), another web standard.

Meeting tokens allow you to manage access and configure the features of your rooms for individual users. We provide API endpoints to create and validate these tokens. But maybe an API request every time you need to create a token is not feasible or preferred. Perhaps you want to create them in bulk, or you are trying to minimize the amount of network requests in general.

This is why these tokens are built on an open standard. You can create them yourself!

Tokens all the way down

Before we dive into creating tokens, let’s look at the anatomy of a JWT.

A JSON Web Token is a trusted and verifiable way to share information. They are digitally “signed” using either a secret (in our case, your API key) or a public/private key pair. They can also be encrypted, but Daily tokens are only signed and any information in them should be treated as public.

A JWT consists of three parts:

  • Header
  • Payload
  • Signature

The header describes the type of token and the algorithm used to sign it.

The payload contains the “claims”. So in the case of a Daily meeting token, that's information like the user_name or room.

The signature is the result of “signing” the header and payload (after base64 encoding them) with the predetermined secret (ex. your API key) using the algorithm defined in the header (ex. HMAC SHA256).

The resulting key will be three base64 encoded strings, each separated by a ., which correspond to the three parts outlined above.

To read more about JWT, check out

Are you token to me?

To create a token you’ll need two things:

  • An API key (get it from our Dashboard)
  • Your domain ID (now available from the / endpoint)

You can query the root (/ ) endpoint, also known as domain configuration, with the following curl command:

curl --request GET \
  --url \
  --header 'Authorization: Bearer INSERT_YOUR_API_KEY_HERE'

You’ll get a response that looks something like this:

    "config": {
    "domain_id": "9cb738e1-5a95-37f1-a517-0a18cf328a39",
    "domain_name": "my-domain-name"

Make note of the domain_id. As mentioned previously, we’ll need this to sign your token.

We have the two things we need to create a token. Let’s consider the payload. A simple payload would look something like this:

  "iat": 1610596413, 
Note: the only required properties are iat and d.

In this case, r is the room name, iat refers to the time (Epoch time) that the token was issued. d is the domain ID you fetched above. You will notice that the property names use a shorthand, you can read the full list of those in our documentation. The short property names are required to keep the resulting token sizes down.

You can create a test token using, being sure to replace the payload with the above (substituting the right values as noted) and adding your API key where it says your-256-bit-secret.

Screenshot of token testing
Example token testing

To validate your token you can run the following curl command:

curl --request GET \
  --url \
  --header 'Authorization: Bearer INSERT_YOUR_API_KEY_HERE'

Read more about this endpoint here.

Token things up a notch

Now you are familiar with how to create and validate a token. Let’s look at an example of how you might integrate one into your own application.

To simplify this we’ve created a little Glitch app that you can remix. Just click this Remix Link  and follow along.

First off, go to the .env file and add your API key and Domain ID (see above if you’re reading ahead) in their respective environment variables.

Now have a look at token.js. We’ll split it into three sections.

In the first part we’re loading the jsonwebtoken library (which was installed in package.json). Next we’re declaring three constants:

  • DOMAIN_ID (loaded via env vars)
  • API_KEY (loaded via env vars)
  • ROOM (a room of your choice)

> Be sure to replace INSERT_ROOM_NAME with a room that exists on your Daily account. You can always create one in the dashboard.

const jwt = require("jsonwebtoken");

const DOMAIN_ID = process.env.DOMAIN_ID;
const API_KEY = process.env.API_KEY;

Next, we’ll create a const called payload, that will be the payload as we discussed earlier. In this example we’re including room (“r”), username (“u”), “iat”, domain_id (“d”), and is_owner (“o”). You can read about all the available properties (and their corresponding shorthands) here.

const payload = {
  "r": ROOM,
  "iat": / 1000,
  "d": DOMAIN_ID,
  "o": true

Last, we specify our algorithm (ALGO). Then create the token itself using the payload, API_KEY, and ALGO by passing them to jwt.sign. Finally, we console.log it (you can view the output by clicking Tools then Logs in the bottom left corner).

const ALGO = { algorithm: "HS256" };

const token = jwt.sign(payload, API_KEY, ALGO);

console.log("token: ", token);  

You can validate the token using our endpoint as described above or using a tool like

What next?

Since the idea behind self-signing tokens is eliminating unnecessary network requests, it’s up to you how to integrate them into your application once they have been created.

A few ideas that come to mind are:

  • Add to an existing auth endpoint
  • Create in bulk via a cron
  • Add to an invite link generator

As always, feel free to share what you’re doing with Daily or give us a shout if we can help!

Never miss a story

Get the latest direct to your inbox.