Only show these results:

How to create and use virtual calendars

This page describes how to authenticate a virtual account and virtual calendar, and how to add an event to your new calendar.

Before you begin

Before you can create a virtual calendar, you need the following prerequisites:

  • A Nylas account.
  • A Nylas application.
  • Your Nylas application's client ID and secret.

Keep in mind

  • Virtual calendars use Custom auth only in v3.
  • Virtual calendars can interact with the Account, Calendar, and Events endpoints only.
  • Each virtual account can have up to ten virtual calendars.

Authenticate a virtual account

Before you can create a virtual calendar, you need a virtual account to represent its "owner". Virtual accounts use Custom auth in v3. You can use the same auth process each time you need to create a new grant for a virtual calendar.

In Nylas v3, you can authenticate a virtual account using either API requests or the Nylas v3 SDKs. Follow these steps to authenticate a virtual account by making API requests:

  1. Create a virtual calendar connector.

    curl --location 'https://api.us.nylas.com/v3/connectors' \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --header 'Authorization: Bearer <NYLAS_API_KEY>' \
    --data '{
    "provider": "virtual-calendar",
    "name": "nylas"
    }'
  2. Create a grant for the virtual account.

    curl --location 'https://api.us.nylas.com/v3/connect/custom' \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --header 'Authorization: Bearer <NYLAS_API_KEY>' \
    --data '{
    "provider": "virtual-calendar",
    "settings": { "email": "devrel-virtual-calendar" },
    "scope": [ "calendar" ]
    }'

    ✨ In Nylas v3, the email property associated with a virtual account does not need to be an email-formatted string.

Authenticate a virtual account with v3 SDKs

You can also authenticate a virtual account using either the Nylas v3 SDKs. Follow these steps to authenticate a virtual account using the Nylas v3 SDKs:

  1. Create a virtual calendar connector.

    import 'dotenv/config'
    import Nylas from 'nylas'

    const NylasConfig = {
    apiKey: process.env.NYLAS_API_KEY,
    apiUri: process.env.NYLAS_API_URI,
    }

    const nylas = new Nylas(NylasConfig)

    async function createConnector() {
    try {
    const connector = await nylas.connectors.create({
    requestBody: {
    name: 'nylas',
    provider: 'virtual-calendar',
    }
    })

    console.log('Connector created:', connector)
    } catch (error) {
    console.error('Error creating provider:', error)
    }
    }

    createConnector()
    from dotenv import load_dotenv
    load_dotenv()
    import os
    import sys
    from nylas import Client

    nylas = Client(
    os.environ.get('NYLAS_API_KEY'),
    os.environ.get('NYLAS_API_URI')
    )

    connector = nylas.connectors.create(
    request_body={
    "name": 'nylas',
    "provider": "virtual-calendar"
    }
    )

    print(connector)
    require 'nylas'

    nylas = Nylas::Client.new(api_key: '<NYLAS_API_KEY>')

    request_body = {
    name: 'Nylas',
    provider: 'virtual-calendar'
    }

    begin
    nylas.connectors.create(request_body: request_body)
    rescue Exception => exception
    puts exception
    end
    import com.nylas.NylasClient;
    import com.nylas.models.*;

    public class connector {
    public static void main(String[] args) throws
    NylasSdkTimeoutError, NylasApiError {

    NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();

    CreateConnectorRequest request =
    new CreateConnectorRequest.VirtualCalendar();
    Response<Connector> connectorResponse =
    nylas.connectors().create(request);
    System.out.println(connectorResponse);
    }
    }
    import com.nylas.NylasClient
    import com.nylas.models.CreateConnectorRequest

    fun main(args: Array<String>) {

    val nylas: NylasClient = NylasClient(
    apiKey = "<NYLAS_API_KEY>"
    )

    val request = CreateConnectorRequest.VirtualCalendar()
    val connector = nylas.connectors().create(request)
    print(connector.data)
    }
  2. Create a grant for the virtual account.

    import 'dotenv/config'
    import Nylas from 'nylas'

    const NylasConfig = {
    apiKey: process.env.NYLAS_API_KEY,
    apiUri: process.env.NYLAS_API_URI,
    }

    const nylas = new Nylas(NylasConfig)

    async function createVirtualCalendarGrant() {
    try {
    const response = await nylas.auth.grants.create({
    requestBody: {
    provider: 'virtual-calendar',
    settings: {
    email: 'devrel-virtual-calendar'
    },
    scope: ['calendar']
    }
    })

    console.log('Grant created:', response)
    } catch (error) {
    console.error('Error creating grant:', error)
    }
    }

    createVirtualCalendarGrant()
    from dotenv import load_dotenv
    load_dotenv()
    import os
    import sys
    from nylas import Client

    nylas = Client(
    os.environ.get('NYLAS_API_KEY'),
    os.environ.get('NYLAS_API_URI')
    )

    grant_id = nylas.auth.custom_authentication(
    request_body={
    "provider": "virtual-calendar",
    "settings": {
    "email": 'devrel-virtual-calendar',
    },
    "scope": ['calendar']
    }
    )

    print(grant_id)
    # frozen_string_literal: true
    require 'nylas'
    require 'sinatra'

    set :show_exceptions, :after_handler

    error 404 do
    'No authorization code returned from Nylas'
    end

    error 500 do
    'Failed to exchange authorization code for token'
    end

    nylas = Nylas::Client.new(api_key: '<NYLAS_API_KEY>')

    get '/nylas/auth' do
    request_body = {
    provider: 'virtual-calendar',
    settings: {
    email: "nylas-virtual-calendar"
    }
    }

    response = nylas.auth.custom_authentication(request_body)
    "#{response}"
    end
    import java.util.*;
    import static spark.Spark.*;
    import com.nylas.NylasClient;
    import com.nylas.models.*;

    public class AuthRequest {
    public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
    NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();

    get("/nylas/auth", (request, response) -> {
    Map<String, String> settings = new HashMap<>();
    settings.put("email", "nylas-virtual-calendar");
    List<String> scopes = new ArrayList<>();
    scopes.add("openid");

    CreateGrantRequest requestBody = new CreateGrantRequest.
    Builder
    (AuthProvider.VIRTUAL_CALENDAR, settings).
    scopes(scopes).state("xyz").build();

    Response<Grant> authResponse = nylas.auth().customAuthentication(requestBody);

    return "%s".formatted(authResponse);
    });
    }
    }
    import com.nylas.NylasClient
    import com.nylas.models.*
    import spark.kotlin.Http
    import spark.kotlin.ignite

    fun main(args: Array<String>) {
    val nylas: NylasClient = NylasClient(apiKey = "<NYLAS_API_KEY>")
    val http: Http = ignite()

    http.get("/nylas/auth") {
    val settings = mapOf("email" to "nylas-virtual-calendar")
    val scopes = listOf("openapi")

    val requestBody = CreateGrantRequest.
    Builder(AuthProvider.VIRTUAL_CALENDAR, settings).
    scopes(scopes).
    state("xyz").
    build()

    var authResponse : Response<Grant>

    nylas.auth().customAuthentication(requestBody).also { authResponse = it }
    authResponse
    }
    }

    ✨ In Nylas v3, the email property associated with a virtual account does not need to be an email-formatted string.

After you create a virtual account you can see it on the Grants page of the Nylas v3 Dashboard.

Create a virtual calendar

Now that you have a virtual account in Nylas, you can create a virtual calendar for the Connected Account or grant.

To create a virtual calendar, make a Create Calendar request or use the v3 SDKs.

curl --location 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/calendars' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <NYLAS_API_KEY>' \
--data '{
"name": "Nylas DevRel",
"description": "Nylas Developer Relations"
}'

import 'dotenv/config'
import Nylas from 'nylas'

const NylasConfig = {
apiKey: process.env.NYLAS_API_KEY,
apiUri: process.env.NYLAS_API_URI,
}

const nylas = new Nylas(NylasConfig)

async function createVirualCalendar() {
try {
const calendar = await nylas.calendars.create({
identifier: process.env.VIRTUAL_CALENDAR_GRANT_ID,
requestBody: {
name: 'Nylas DevRel',
description: 'Nylas Developer Relations',
}
})

console.log('Virtual Calendar:', calendar)
} catch (error) {
console.error('Error to create virtual calendar:', error)
}
}

createVirualCalendar()
from dotenv import load_dotenv
load_dotenv()

import os
import sys
from nylas import Client

nylas = Client(
os.environ.get('NYLAS_API_KEY'),
os.environ.get('NYLAS_API_URI')
)

grant_id = os.environ.get("VIRTUAL_CALENDAR_GRANT_ID")

calendar = nylas.calendars.create(
grant_id,
request_body={
"name": 'Nylas DevRel',
"description": 'Nylas Developer Relations'
}
)

print(calendar)
require 'nylas' 

nylas = Nylas::Client.new(api_key: '<NYLAS_API_KEY>')

request_body = {
"name": "Nylas DevRel",
"description": "Nylas Developer Relations",
"timezone": "America/Toronto"
}

begin
calendars, _request_ids = nylas.calendars.create(
identifier: '<VIRTUAL_CALENDAR_ID>',
request_body: request_body)

puts calendars
rescue Exception => exception
puts exception
end
import com.nylas.NylasClient;
import com.nylas.models.*;
import java.util.HashMap;

public class CreateVirtualCalendar {
public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();

CreateCalendarRequest requestBody = new CreateCalendarRequest(
"Nylas DevRel",
"Nylas Developer Relations",
"Nylas Headquarters",
"America/Toronto",
new HashMap<String, String>());

try {
Response<Calendar> calendar = nylas.calendars().create(
"<VIRTUAL_CALENDAR_GRANT_ID>",
requestBody);

System.out.println(calendar);
} catch(Exception e) {
System.out.printf(" %s%n", e);
}
}
}
import com.nylas.NylasClient
import com.nylas.models.*

fun main(args: Array<String>) {
val nylas: NylasClient = NylasClient(apiKey = "<NYLAS_API_KEY>")

val requestBody = CreateCalendarRequest(
"Nylas DevRel",
"Nylas Developer Relations",
"Nylas Headquarters",
"America/Toronto",
mapOf<String, String>()
)

val calendar: Response<Calendar> = nylas.calendars().create(
"<VIRTUAL_CALENDAR_GRANT_ID>",
requestBody)

print(calendar.data)
}

Create an event on a virtual calendar

Now that you have both a virtual account and a virtual calendar associated with it, you can start creating events.

⚠️ Virtual calendars do not send invitations to event participants. The ability to send invitations by generating an ICS file is coming soon for v3.

To create an event on your virtual calendar, make a Create Event request or use the v3 SDKs.

curl --location 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/events?calendar_id=<CALENDAR_ID>&notify_participants=true' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <NYLAS_API_KEY>' \
--data '{
"when": {
"start_time": 1704302073,
"end_time": 1704305673
},
"title": "Build With Nylas"
}'
import 'dotenv/config'
import Nylas from 'nylas'

const NylasConfig = {
apiKey: process.env.NYLAS_API_KEY,
apiUri: process.env.NYLAS_API_URI
}

const nylas = new Nylas(NylasConfig)
const now = Math.floor(Date.now() / 1000)

async function createAnEvent() {
try {
const event = await nylas.events.create({
identifier: process.env.VIRTUAL_CALENDAR_GRANT_ID,
requestBody: {
title: 'Build With Nylas',
when: {
startTime: now,
endTime: now + 3600,
}
},
queryParams: {
calendarId: process.env.VIRTUAL_CALENDAR_ID,
},
})

console.log('Event:', event)
} catch (error) {
console.error('Error creating event:', error)
}
}

createAnEvent()
from dotenv import load_dotenv
load_dotenv()

import os
import sys
from nylas import Client

nylas = Client(
os.environ.get('NYLAS_API_KEY'),
os.environ.get('NYLAS_API_URI')
)

grant_id = os.environ.get("VIRTUAL_CALENDAR_GRANT_ID")
calendar_id = os.environ.get("VIRTUAL_CALENDAR_ID")

events = nylas.events.create(
grant_id,
request_body={
"title": 'Build With Nylas',
"when": {
"start_time": 1609372800,
"end_time": 1609376400
},
},
query_params={
calendar_id
}
)

print(events)
require 'nylas'

nylas = Nylas::Client.new(api_key: '<NYLAS_API_KEY>')

query_params = {
calendar_id: '<VIRTUAL_CALENDAR_ID>'
}

start_time = Time.now.to_i
end_time = start_time + 3600

request_body = {
when: {
start_time: start_time,
end_time: end_time
},
title: "Build With Nylas",
}

events, _request_ids = nylas.events.create(
identifier: '<VIRTUAL_CALENDAR_GRANT_ID>',
query_params: query_params,
request_body: request_body)

if _request_ids != ""
puts events[:id]
puts events[:title]
puts "Event created successfully"
else
puts "There was an error creating the event"
end
import com.nylas.NylasClient;
import com.nylas.models.*;

public class CreateVirtualEvent {
public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();

CreateEventRequest.When.Timespan timespan = new CreateEventRequest.When.Timespan.
Builder
(Math.toIntExact("<START_TIME>"),
Math.toIntExact("<END_TIME>")).
build();

CreateEventRequest request = new CreateEventRequest.Builder(timespan).
title("Build With Nylas").
build();

CreateEventQueryParams queryParams = new CreateEventQueryParams.Builder("<VIRTUAL_CALENDAR_ID>").build();

Response<Event> event = nylas.events().create(
"<VIRTUAL_CALENDAR_GRANT_ID",
request,
queryParams);

System.out.println(event);
}
}
import com.nylas.NylasClient
import com.nylas.models.*

fun main(args: Array<String>) {
val nylas: NylasClient = NylasClient(apiKey = "<NYLAS_API_KEY>")

val eventWhenObj: CreateEventRequest.When = CreateEventRequest.When.Timespan(<START_TIME>, <END_TIME>)

val eventRequest: CreateEventRequest = CreateEventRequest.Builder(eventWhenObj).
title("Nylas DevRel").
description("Nylas Developer Relations").
location("Nylas Headquarters").
build()

val eventQueryParams: CreateEventQueryParams = CreateEventQueryParams("<VIRTUAL_CALENDAR_ID>")

val event: Response<Event> = nylas.events().create(
"<VIRTUAL_CALENDAR_GRANT_ID>",
eventRequest,
eventQueryParams)

print(event.data)
}

Nylas creates the event and adds it to the virtual calendar.