# Calendars & Events

In this guide we'll get you started as quickly as possible with the Cronofy Calendar API. This will cover:

- Getting authorization to access a calendar

- Reading events

- Creating your first event

## Authorization
The very first thing to do is obtain authorization to access a user's calendars. Cronofy acts as an intermediary between your application and the various calendar services in use.

We act as an [OAuth2](https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified) provider to your application so the API access is via a user specific `access_token`.

Once you've [signed up for a Developer Account](https://app.cronofy.com/sign_up/developer), you can [create an Application](https://app.cronofy.com/oauth/applications).

![](/developers/calendars-events/create-app.8994003d67b360391736ce3e995f792e89af5e996c03e9fdb04991a5cc5075b1.png)
With your Application created, you will be able to connect your calendar by following the OAuth journey.

![](/developers/calendars-events/auth-to-app.e1d02fecb7ad3754be5bef5f030c34d0b4417b33ea9959f7187c2d4aed2217ed.png)
Once you've connected your calendar, you will be able to view your `access_token` and you are ready to start making API calls.

## Reading Events
The Cronofy API allows you to read all events across all calendars for all providers with one call. The only mandatory parameter is the `tzid`, ie. time zone identifier, for which you want to read.

The example below is for UTC, but you can also use `Europe/Paris`, `America/Chicago` or any identifier in the <a href="https://www.iana.org/time-zones" target="_blank" rel="noopener">IANA Time Zone Database</a>.



```bash
curl -v -G --header "Authorization: Bearer {YOUR_ACCESS_TOKEN_HERE}" \
  -d 'tzid=Etc/UTC' https://api.cronofy.com/v1/events
```


```ruby
cronofy = Cronofy::Client.new(access_token: '{YOUR_ACCESS_TOKEN_HERE}')
events = cronofy.read_events
```


```csharp
var cronofy = new CronofyAccountClient("{YOUR_ACCESS_TOKEN_HERE}");
var events = cronofy.GetEvents();
```

```javascript
var options = {
    access_token: '{YOUR_ACCESS_TOKEN_HERE}',
    tzid: 'Etc/UTC'
};

cronofy.readEvents(options)
    .then(function (response) {
        var events = response.events;
    });
```


```php
$cronofy = new Cronofy('', '', '{YOUR_ACCESS_TOKEN_HERE}', '');

$events = $cronofy->read_events(array('tzid' => 'Etc/UTC'));
```


```python
import pycronofy

cronofy = pycronofy.Client(access_token="{YOUR_ACCESS_TOKEN_HERE}")
events = cronofy.read_events()
```



This will return JSON formatted results similar to this:

```json
{
  "events": [
    {
      "calendar_id": "cal_U9uuErStTG@EAAAB_IsAsykA2DBTWqQTf-f0kJw",
      "event_uid": "evt_external_54008b1a4a41730f8d5c6037",
      "summary": "Company Retreat",
      "description": "",
      "start": "2026-04-21",
      "end": "2026-04-21",
      "deleted": false,
      "location": {
        "description": "Beach"
      },
      "participation_status": "needs_action",
      "transparency": "opaque",
      "event_status": "confirmed",
      "categories": [],
      "attendees": [
        {
          "email": "example@cronofy.com",
          "display_name": "Example Person",
          "status": "needs_action"
        }
      ],
      "created": "2026-04-17T08:00:01Z",
      "updated": "2026-04-17T09:24:16Z"
    }
  ]
}
```

You'll see that the response is also setup for paging, so if there is more than one page you can request the next one by using the url supplied in `pages.next_page`.

By default the events returned are from [42 days](/developers/api/events/read-events/index.md) in the past to [201 days](/developers/api/events/read-events/index.md) in the future. You can specify `from` and `to` parameters to refine that search.

For example, the following will return events between, and including, **2026-04-17** and **2026-04-22**.



```bash
curl -v -G --header "Authorization: Bearer {YOUR_ACCESS_TOKEN_HERE}" \
  -d 'tzid=Etc/UTC&from=2026-04-17&to=2026-04-22' https://api.cronofy.com/v1/events
```


```ruby
cronofy = Cronofy::Client.new(access_token: '{YOUR_ACCESS_TOKEN_HERE}')
events = cronofy.read_events(from: Date.new(2026, 4, 17), to: Date.new(2026, 4, 22))
```


```csharp
var cronofy = new CronofyAccountClient("{YOUR_ACCESS_TOKEN_HERE}");
var builder = new GetEventsRequestBuilder()
                    .From(2026, 4, 17)
                    .To(2026, 4, 22);
var events = client.GetEvents(builder);
```


```javascript
var options = {
    access_token: '{YOUR_ACCESS_TOKEN_HERE}',
    tzid: 'Etc/UTC',
    from: '2026-04-17',
    to: '2026-04-22'
};

cronofy.readEvents(options)
    .then(function (response) {
        var events = response.events;
    });
```


```php
$cronofy = new Cronofy('', '', '{YOUR_ACCESS_TOKEN_HERE}', '');

$params = array(
    'tzid' => 'Etc/UTC',
    'from' => '2026-04-17',
    'to' => '2026-04-22'
);
$events = $cronofy->read_events($params);
```


```python
import pycronofy

cronofy = pycronofy.Client(access_token="{YOUR_ACCESS_TOKEN_HERE}")
events = cronofy.read_events(
    from_date='2026-04-17',
    to_date='2026-04-22',
    tzid='Etc/UTC')
```



For more details see [Read Events.](/developers/api/events/read-events/index.md)

## Creating a Calendar Event
The first step is to get the `calendar_id` for the calendar you want to insert the event into.



```bash
curl -v --header "Authorization: Bearer {YOUR_ACCESS_TOKEN_HERE}" \
    https://api.cronofy.com/v1/calendars
```


```ruby
cronofy = Cronofy::Client.new(access_token: '{YOUR_ACCESS_TOKEN_HERE}')
calendars = cronofy.list_calendars
```


```csharp
var cronofy = new CronofyAccountClient("{YOUR_ACCESS_TOKEN_HERE}");
var calendars = cronofy.GetCalendars();
```


```javascript
cronofy.listCalendars({ access_token: '{YOUR_ACCESS_TOKEN_HERE}'})
    .then(function (response) {
        var calendars = response.calendars;
    });
```


```php
$cronofy = new Cronofy('', '', '{YOUR_ACCESS_TOKEN_HERE}', '');

$calendars = $cronofy->list_calendars();
```


```python
import pycronofy

cronofy = pycronofy.Client(access_token="{YOUR_ACCESS_TOKEN_HERE}")
calendars = cronofy.list_calendars()
```



This will give you a response similar to this:

```json
{
  "calendars": [
    {
      "provider_name": "google",
      "profile_id": "pro_n23kjnwrw2",
      "profile_name": "example@cronofy.com",
      "calendar_id": "cal_n23kjnwrw2_jsdfjksn234",
      "calendar_name": "Home",
      "calendar_readonly": false,
      "calendar_deleted": false
    },
    {
      "provider_name": "apple",
      "profile_id": "pro_n23kjnwrw2",
      "profile_name": "example@cronofy.com",
      "calendar_id": "cal_n23kjnwrw2_3nkj23wejk1",
      "calendar_name": "Bank Holidays",
      "calendar_readonly": true,
      "calendar_deleted": false
    }
  ]
}
```

The `calendar_id` is the internal Cronofy identifier for the calendar. You can then create an event by posting a JSON formatted payload.

Lets say you want to create the follow event in a specific calendar:

```json
{
  "event_id": "qTtZdczOccgaPncGJaCiLg",
  "summary": "Board meeting",
  "description": "Discuss plans for the next quarter.",
  "start": "2026-04-17T15:30:00Z",
  "end": "2026-04-17T17:00:00Z",
  "location": {
    "description": "Board room"
  }
}
```

Then you would post the following:



```bash
curl -v --header "Authorization: Bearer {YOUR_ACCESS_TOKEN_HERE}" \
    --header "Content-Type: application/json" \
    --data "{\"event_id\": \"qTtZdczOccgaPncGJaCiLg\",\"summary\": \"Board meeting\",\"description\": \"Discuss plans for the next quarter.\",\"start\": \"2026-04-17T15:30:00Z\",\"end\": \"2026-04-17T17:00:00Z\",\"location\": {\"description\": \"Board room\"}}" \
    https://api.cronofy.com/v1/calendars/{CALENDAR_ID}/events
```


```ruby
cronofy = Cronofy::Client.new(access_token: '{YOUR_ACCESS_TOKEN_HERE}')
new_event = {
  event_id: "qTtZdczOccgaPncGJaCiLg",
  summary: "Board meeting",
  description: "Discuss plans for the next quarter.",
  start: Time.parse("2026-04-17T15:30:00Z"),
  end: Time.parse("2026-04-17T17:00:00Z"),
  location: {
    description: "Board room"
  }
}

cronofy.upsert_event(calendar_id, new_event)
```


```csharp
var cronofy = new CronofyAccountClient("{YOUR_ACCESS_TOKEN_HERE}");
var eventBuilder = new UpsertEventRequestBuilder()
                        .EventId("uniq-id")
                        .Summary("Event summary")
                        .Description("Event description")
                        .Start(2026, 4, 17, 17, 00)
                        .End(2026, 4, 17, 17, 30)
                        .Location("Meeting room");

cronofy.UpsertEvent(calendarId, eventBuilder);
```


```javascript
var options = {
    access_token: '{YOUR_ACCESS_TOKEN_HERE}',
    event_id: "qTtZdczOccgaPncGJaCiLg",
    summary: "Board meeting",
    description: "Discuss plans for the next quarter.",
    start: "2026-04-17T15:30:00Z",
    end: "2026-04-17T17:00:00Z",
    location: {
        description: "Board room"
    }
};

cronofy.createEvent(options)
    .then(function () {
        // Success
    });
```


```php
$cronofy = new Cronofy('', '', '{YOUR_ACCESS_TOKEN_HERE}', '');

$params = array(
    'calendar_id' => $calendarId,
    'event_id' => 'qTtZdczOccgaPncGJaCiLg',
    'summary' => 'Board meeting',
    'description' => 'Discuss plans for the next quarter.',
    'start' => '2026-04-17T15:30:00Z',
    'end' => '2026-04-17T17:00:00Z'
);

$cronofy->upsert_event($params);
```


```python
import pycronofy

cronofy = pycronofy.Client(access_token="{YOUR_ACCESS_TOKEN_HERE}")
event = {
    'event_id': "qTtZdczOccgaPncGJaCiLg",
    'summary': "Board meeting",
    'description': "Discuss plans for the next quarter.",
    'start': "2026-04-17T15:30:00Z",
    'end': "2026-04-17T17:00:00Z",
    'location': {
        'description': "Board room"
    }
}
cronofy.upsert_event(calendar_id=calendar_id, event=event)
```



### Creating an all-day event
To create an all-day event, you just pass the `start` and `end` parameters as [ISO 8601 Dates](https://www.iso.org/iso-8601-date-and-time-format.html).

Please note that the `end` parameter is **exclusive**. The `end` value is always the day **after** the end of the all-day event period.

```json
{
  "event_id": "qTtZdczOccgaPncGJaCiLg",
  "summary": "Away for off-site",
  "description": "Discuss plans for the next quarter.",
  "start": "2026-04-17",
  "end": "2026-04-18",
  "tzid": "America/Chicago",
  "location": {
    "description": "Board room"
  }
}
```

To create the above all-day event you would post the following:



```bash
curl -v --header "Authorization: Bearer {YOUR_ACCESS_TOKEN_HERE}" \
    --header "Content-Type: application/json" \
    --data "{\"event_id\": \"qTtZdczOccgaPncGJaCiLg\",\"summary\": \"Away for off-site\",\"description\": \"Discuss plans for the next quarter.\",\"start\": \"2026-04-17\",\"end\": \"2026-04-18\",\"location\": {\"description\": \"Board room\"}}" \
    https://api.cronofy.com/v1/calendars/{CALENDAR_ID}/events
```


```ruby
cronofy = Cronofy::Client.new(access_token: '{YOUR_ACCESS_TOKEN_HERE}')
new_event = {
  event_id: "qTtZdczOccgaPncGJaCiLg",
  summary: "Away for off-site",
  description: "Discuss plans for the next quarter.",
  start: Date.new(2026, 4, 17),
  end: Date.new(2026, 4, 18),
  location: {
    description: "Board room"
  }
}

cronofy.upsert_event(calendar_id, new_event)
```


```csharp
var cronofy = new CronofyAccountClient("{YOUR_ACCESS_TOKEN_HERE}");
var eventBuilder = new UpsertEventRequestBuilder()
                        .EventId("qTtZdczOccgaPncGJaCiLg")
                        .Summary("Away for off-site")
                        .Description("Event description")
                        .Start(2026, 4, 17)
                        .End(2026, 4, 18)
                        .TimeZoneId("America/Chicago")
                        .Location("Meeting room");

cronofy.UpsertEvent(calendarId, eventBuilder);
```


```javascript
var options = {
    access_token: '{YOUR_ACCESS_TOKEN_HERE}',
    event_id: "qTtZdczOccgaPncGJaCiLg",
    summary: "Away for off-site",
    description: "Discuss plans for the next quarter.",
    start: "2026-04-17",
    end: "2026-04-18",
    tzid: "America/Chicago",
    location: {
        description: "Board room"
    }
};

cronofy.createEvent(options)
    .then(function () {
        // Success
    });
```


```php
$cronofy = new Cronofy('', '', '{YOUR_ACCESS_TOKEN_HERE}', '');

$params = array(
    'calendar_id' => $calendarId,
    'event_id' => 'qTtZdczOccgaPncGJaCiLg',
    'summary' => 'Away for off-site',
    'description' => 'Discuss plans for the next quarter.',
    'start' => '2026-04-17',
    'end' => '2026-04-18',
    'tzid' => 'America/Chicago'
);

$cronofy->upsert_event($params);
```


```python
import pycronofy

cronofy = pycronofy.Client(access_token="{YOUR_ACCESS_TOKEN_HERE}")
event = {
    'event_id': "qTtZdczOccgaPncGJaCiLg",
    'summary': "Away for off-site",
    'description': "Discuss plans for the next quarter.",
    'start': "2026-04-17",
    'end': "2026-04-18",
    'tzid': "America/Chicago",
    'location': {
        'description': "Board room"
    }
}
cronofy.upsert_event(calendar_id=calendar_id, event=event)
```



Also see docs for [Create or Update Event](/developers/api/events/upsert-event/index.md).


---
[Read in HTML](/developers/calendars-events/)

## In this section

- [Time Zones](/developers/calendars-events/time-zones/index.md) — How time and time zones are used with the Cronofy API.
- [Filtering Events](/developers/calendars-events/event-filtering/index.md) — A summary of the event filtering parameters and how they interact.
- [Application Calendars](/developers/calendars-events/application-calendars/index.md) — An introduction to Application Calendars and how to use them as a drop in replacement for end-user or resource calendars.
- [Editing Events](/developers/calendars-events/editing-events/index.md) — How to edit External Events using the Cronofy API
