Issue with virtual calendar and hosting url

Hello,

I’m trying to build something for my customer, I’m working with dart and GCP with node

When my user is created, here is the flow

const functions = require("firebase-functions");

const admin = require("firebase-admin");

const axios = require("axios");




if (!admin.apps.length) admin.initializeApp();




function generateSlug(name, uid) {

    if (!name) return `${uid}-booking`;

    return (

        name

            .toLowerCase()

            .normalize("NFD")

            .replace(/[\u0300-\u036f]/g, "")

            .replace(/[^a-z0-9]+/g, "-")

            .replace(/^-+|-+$/g, "")

            .substring(0, 50) +

        `-${uid.slice(0, 6)}`

    );

}




exports.onUserCreated = functions

    .region("europe-west1")

    .auth.user()

    .onCreate(async (user) => {

        const firestore = admin.firestore();

        const nylasApiKey =

            "***";




        try {

            console.log("🆕 New user:", user.uid, user.email);




            // 1️⃣ Create Virtual Calendar Grant

            const grantResp = await axios.post(

                "https://api.eu.nylas.com/v3/grants",

                {

                    provider: "virtual-calendar",

                    name: user.displayName || "User Calendar",

                    settings: { email: user.email },

                    scope: ["calendar"],

                },

                { headers: { Authorization: `Bearer ${nylasApiKey}` } }

            );




            const grantId = grantResp.data.data.id;

            console.log("✅ Grant created:", grantId);




            // 2️⃣ Create Virtual Calendar under this Grant

            const calendarResp = await axios.post(

                `https://api.eu.nylas.com/v3/grants/${grantId}/calendars`,

                {

                    name: `${user.displayName || "User"} Calendar`,

                    description: "Primary virtual calendar for scheduling",

                },

                { headers: { Authorization: `Bearer ${nylasApiKey}` } }

            );




            const calendarId = calendarResp.data.data.id;

            console.log("✅ Virtual calendar created:", calendarId);




            // 3️⃣ Generate slug

            const slug = generateSlug(user.displayName, user.uid);




            // 4️⃣ Create Scheduler Configuration (auto-hosted)

            const schedulerResp = await axios.post(

                `https://api.eu.nylas.com/v3/grants/${grantId}/scheduling/configurations`,

                {

                    slug: slug,

                    requires_session_auth: false,

                    round_robin: false, // <-- this fixes the organizer error

                    participants: [

                        {

                            name: user.displayName || "Organizer",

                            email: user.email,

                            is_organizer: true,

                            grant_id: grantId,

                            availability: {

                                calendar_ids: [calendarId],

                                open_hours: [

                                    {

                                        days: [1, 2, 3, 4, 5],

                                        timezone: "Europe/Paris",

                                        start: "09:00",

                                        end: "17:00",

                                        exdates: [],

                                    },

                                ],

                            },

                            booking: { calendar_id: calendarId },

                        },

                    ],

                    availability: {

                        duration_minutes: 30,

                        interval_minutes: 30,

                    },

                    event_booking: {

                        title: "Meeting with " + (user.displayName || "User"),

                    },

                },

                { headers: { Authorization: `Bearer ${nylasApiKey}` } }

            );





            const scheduler = schedulerResp.data.data;

            console.log("✅ Scheduler created:", scheduler.id);

            console.log("🔗 Scheduler data:", scheduler);




            const hostedUrl = `https://book.nylas.com/${slug}`;

            console.log("🔗 Hosted URL:", hostedUrl);

            

            // 5️⃣ Save to Firestore

            await firestore.collection("users").doc(user.uid).set(

                {

                    nylas_grant_id: grantId,

                    nylas_calendar_id: calendarId,

                    nylas_scheduler_id: scheduler.id,

                    nylas_scheduler_slug: slug,

                    nylas_scheduler_url:

                        scheduler.hosted_url || `https://book.nylas.com/${slug}`,

                },

                { merge: true }

            );




            console.log("✅ Nylas setup completed for:", user.uid);

        } catch (err) {

            console.error(

                "❌ Nylas setup error:",

                err.response?.data || err.message

            );

        }

    });

And here are the response log

{
“logs”: [
{
“timestamp”: “2025-10-17T08:38:29.330862Z”,
“level”: “INFO”,
“message”: “:new_button: New user: lxMlbTtXZwNsKhlclnnq1iFVMKg1 ***@gmail.comgmail.com
},
{
“timestamp”: “2025-10-17T08:38:30.220065Z”,
“level”: “INFO”,
“message”: “:white_check_mark: Grant created: df10e1b1-7bbf-4dd4-8eb1-6a1591ad6336”
},
{
“timestamp”: “2025-10-17T08:38:30.432640Z”,
“level”: “INFO”,
“message”: “:white_check_mark: Virtual calendar created: 7a707781-aada-4b94-b9f8-16ab538b1cec”
},
{
“timestamp”: “2025-10-17T08:38:30.608522Z”,
“level”: “INFO”,
“message”: “:white_check_mark: Scheduler created: cdd602f5-3491-4f24-888c-9e5eda9c860a”
},
{
“timestamp”: “2025-10-17T08:38:30.611121Z”,
“level”: “INFO”,
“message”: “:link: Hosted URL: Nylas - Scheduler v3
},
{
“timestamp”: “2025-10-17T08:38:34.276445Z”,
“level”: “INFO”,
“message”: “:white_check_mark: Nylas setup completed for: lxMlbTtXZwNsKhlclnnq1iFVMKg1”
}
]
}

With detailed schedulerResp

{
“id”: “cdd602f5-3491-4f24-888c-9e5eda9c860a”,
“slug”: “lxMlbTtXZwNsKhlclnnq1iFVMKg1-booking”,
“participants”: [
{
“name”: “Organizer”,
“email”: “***@gmail.com”,
“is_organizer”: true,
“grant_id”: “df10e1b1-7bbf-4dd4-8eb1-6a1591ad6336”,
“availability”: {
“calendar_ids”: [“7a707781-aada-4b94-b9f8-16ab538b1cec”],
“open_hours”: [
{
“days”: [1,2,3,4,5],
“timezone”: “Europe/Paris”,
“start”: “09:00”,
“end”: “17:00”,
“exdates”:
}
]
},
“booking”: {
“calendar_id”: “7a707781-aada-4b94-b9f8-16ab538b1cec”
}
}
],
“requires_session_auth”: false,
“availability”: {
“duration_minutes”: 30,
“interval_minutes”: 30
},
“event_booking”: {
“title”: “Meeting with User”,
“booking_type”: “booking”,
“hide_participants”: null,
“disable_emails”: null
},
“scheduler”: {
“available_days_in_future”: 30,
“min_cancellation_notice”: 0,
“min_booking_notice”: 60,
“hide_rescheduling_options”: false,
“hide_cancellation_options”: false,
“email_template”: {
“booking_confirmed”: {}
}
},
“appearance”: null,
“hosted_url”: “Nylas - Scheduler v3
}

It’s been few days I can’t get why the hosted URL not working even tho I followed the doc, did someone had similar issue please ?

Hello @Habari1447,

Our Support team has reached out to you via email to continue this investigation. Please check your mailbox for our message.

Many thanks,
Samuel R.
Support Engineer, Nylas