Version:
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 must complete the following tasks:

Keep in mind

Keep the following information in mind as you work with virtual calendars:

  • Virtual calendars use Custom authentication only in Nylas v3.
  • Virtual calendars can interact with the Grants, Calendar, and Events endpoints only.
  • Each virtual account can have up to 10 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 --request POST \
    --url '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 --request POST \
    --url '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 --request POST \
--url '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.

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

curl --request POST \
--url '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.