Call out functionality in the UI Toolkit

Hi,

I’m using the UI Toolkit to add the Zoom functionality in my app and that is working fine. I purchased the Audio conference subscription last week to be able to invite third parties by phone number.

In the release notes I see that the PSTN call out functionality is added but I cannot find any documentation how to add this to my configuration.

Hopefully someone can point me in the right direction because this is a crucial functionality in the workflow of my app.

Kind Regards,

Ferdi

Hi @idref10, which release notes are you referring to?

Hi,

For example:

I see, we’re working on adding UI for using PSTN within the UITookit on Web. In the meantime you can use the REST API for this:

const callInPtsn = () => {
        return fetch('https://api.zoom.us/v2/videosdk/sessions/{SESSIONID}/events', {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/json',
        "Authorization": "Bearer {VSDK_JWT}"
      },
  body: JSON.stringify({
    "method": "user.invite.callout",
    "params":{
        "invitee_name":"Your Name",
        "phone_number":"1234567890"
    }
}),
}).then(response => response.json())
  .then(data => console.log(data))
}

You can access the SESSIONID in the UI or use the webhook/REST API to get it:

Okay great, for now I’m going to use the REST API and in the meantime I’m waiting for an update according the UIToolkit.

Thanks for your response.

Kind Regards,

Ferdi

1 Like
const {onCall, HttpsError} = require("firebase-functions/v2/https");
const {defineSecret} = require("firebase-functions/params");
const jwt = require("jsonwebtoken");

// Define Zoom Secrets
const zoomApiKey = defineSecret("ZOOM_SDK_KEY");
const zoomApiSecret = defineSecret("ZOOM_SDK_SECRET");

/**
 * Function to generate Zoom JWT Token
 */
exports.generateZoomToken = onCall(
    {secrets: [zoomApiKey, zoomApiSecret]},
    async (req, context) => {
      const {tpc, roleType} = req.data; // No spaces after '{' and before '}'

      // Validate inputs
      if (!tpc) {
        throw new HttpsError("invalid-argument", "Topic is required.");
      }

      // Define payload for JWT
      const payload = {
        app_key: zoomApiKey.value(),
        tpc: tpc, // Session Name
        version: 1,
        role_type: roleType || 0,
        iat: Math.floor(Date.now() / 1000) - 30,
        exp: Math.floor(Date.now() / 1000) + 60 * 60 * 2,
      };

      // Generate JWT Token
      const token = jwt.sign(payload, zoomApiSecret.value());

      return {token}; // Added trailing comma as needed
    },
);

exports.inviteByPhone = onCall(
    {secrets: [zoomApiKey, zoomApiSecret]},
    async (req, context) => {
      const {sessionId, inviteeName, phoneNumber} = req.data;

      // Validate inputs
      if (!sessionId || !inviteeName || !phoneNumber) {
        throw new HttpsError("invalid-argument", "Need args.");
      }

      try {
        // Generate JWT Token
        const payload = {
          app_key: zoomApiKey.value(),
          tpc: sessionId, // Assuming 'tpc' is used as session name
          version: 1,
          role_type: 0,
          iat: Math.floor(Date.now() / 1000) - 30,
          exp: Math.floor(Date.now() / 1000) + 60 * 60 * 2,
        };

        const token = jwt.sign(payload, zoomApiSecret.value());

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

        // Prepare the API endpoint
        const url = `https://api.zoom.us/v2/videosdk/sessions/${sessionId}/events`;

        // Make the API request to invite by phone
        const response = await fetch(url, {
          method: "PATCH",
          headers: {
            "Content-Type": "application/json",
            "Authorization": `Bearer ${token}`,
          },
          body: JSON.stringify({
            method: "user.invite.callout",
            params: {
              invitee_name: inviteeName,
              phone_number: phoneNumber,
            },
          }),
        });

        const data = await response.json();

        if (!response.ok) {
          console.error("Zoom API Error:", data);
          throw new HttpsError("internal",
              data.message || "Failed to invite by phone.");
        }

        return {success: true, data};
      } catch (error) {
        console.error("Error inviting by phone:", error);
        throw new HttpsError("internal",
            error.message || "An error occurred while inviting by phone.");
      }
    },
);

I have these 2 functions.

GenerateZoomToken i use to create the token to initiate the call which is working fine.

When I try to call the rest API I get the message Error inviting by phone: HttpsError: Invalid access token.

What Am I missing here?

Sorry for my questions but I found out that I was mixing up the different API keys with the SDK keys so I have the token creation working.

The only thing that I cannot fix is how to retrieve the Session Id with the UI Toolkit. I need this to call the endpoint and in my previous example I was using the session name which are obvious different.

The event listeners don’t give me the Session Id so I’,m wondering where I can find this.

Small update

I changed my workflow and I now first create the session with the API so I have the session ID. That works fine but now when i call the API for the events I get a response 400 bad request.

This is my API call

const url = `https://api.zoom.us/v2/videosdk/sessions/${sessionId}/events`;

        // Make the API request to invite by phone
        const response = await fetch(url, {
          method: "PATCH",
          headers: {
            "Content-Type": "application/json",
            "Authorization": `Bearer ${token}`,
          },
          body: JSON.stringify({
            method: "user.invite.callout",
            params: {
              invitee_name: inviteeName,
              phone_number: phoneNumber,
            },
          }),
        });

Another small update

I was using the phonenumber with a + instead of double zero and now it is working!

1 Like