Source: https://cli.nylas.com/guides/export-calendar-events-cli

# Export Calendar Events to CSV & JSON (CLI)

Export calendar events to CSV or JSON from the terminal. Use nylas calendar events list with jq to build backup files, reports, and spreadsheets in seconds.

Written by [Hazik](https://cli.nylas.com/authors/hazik) Director of Product Management

Updated June 9, 2026

> **TL;DR:** Run [`nylas calendar events list --days N --json`](https://cli.nylas.com/docs/commands/calendar-events-list) and pipe through `jq -r '.[] | [.title,.when.start_time,.when.end_time] | @csv'` for a CSV, or redirect the raw `--json` output to a file for JSON. One command; no export button needed.

Command references used in this guide: [`nylas calendar events list`](https://cli.nylas.com/docs/commands/calendar-events-list), [`nylas calendar list`](https://cli.nylas.com/docs/commands/calendar-list), and [`nylas calendar events show`](https://cli.nylas.com/docs/commands/calendar-events-show).

## Why export calendar events from the terminal?

Google Calendar's native export produces an ICS file — a format designed for calendar apps, not spreadsheets or databases. ICS is great for importing into another calendar, but terrible for pivot tables, SQL queries, or feeding a reporting tool. CSV and JSON are what analysts, engineers, and automation scripts actually want, and neither format has a native "Export" button in any major calendar provider's UI. According to a 2024 survey by State of the API, 62% of developers cite data export friction as a top integration pain point.

The Nylas CLI solves this in one command. `nylas calendar events list --json` returns structured event data directly; jq's `@csv` operator turns it into RFC 4180-compliant rows. You can export 30 days of events in under 5 seconds, script it into a cron job, or pipe it into any downstream tool.

## How do you export calendar events to JSON?

Exporting calendar events to JSON means redirecting the `--json` flag's output to a file. The flag tells the CLI to emit structured JSON instead of the default human-readable table. Each event in the array carries fields including `title`, `when.start_time`, `when.end_time`, `location`, `organizer`, and `participants`. A 90-day export of a busy calendar typically produces a file between 50 KB and 500 KB depending on event density.

The `--days` flag sets the look-ahead window. The default is 7 days. Use 30 for a monthly backup or 90 for a quarterly archive. If you need a specific date range, combine `--days` with the current date to calculate the window. JSON is the right format for backup and analysis because it preserves every field; use CSV only when you need a spreadsheet.

```bash
# Export the next 30 days as JSON
nylas calendar events list --days 30 --json > calendar-export.json

# Verify the file
jq 'length' calendar-export.json       # number of events
jq '.[0] | keys' calendar-export.json  # available fields on the first event
```

## How do you export calendar events to CSV?

Exporting calendar events to CSV uses jq's `@csv` operator, which formats an array of values as one correctly quoted CSV row per call. This operator implements the quoting rules from [RFC 4180](https://datatracker.ietf.org/doc/html/rfc4180), so event titles containing commas, quotes, or newlines are escaped correctly. A naive comma-join breaks on those characters; `@csv` handles them in one operator. The [jq manual](https://stedolan.github.io/jq/manual/) documents `@csv` under the Format strings section. The `-r` flag on jq prints raw output so the file contains literal CSV rather than JSON-escaped strings.

Print a header row first, then one row per event. The column order in the jq array matches the column order in the file, so you can add or remove columns by editing the array. Include a null-safe fallback (`// ""`) for optional fields like `location` — a missing value would otherwise produce a short row that misaligns the spreadsheet by one cell. A typical 30-day export finishes in under 3 seconds.

```bash
# Export the next 30 days to CSV with a header row
{
  echo 'title,start,end,location'
  nylas calendar events list --days 30 --json     | jq -r '.[] | [
        (.title // ""),
        (.when.start_time // ""),
        (.when.end_time // ""),
        (.location // "")
      ] | @csv'
} > calendar-export.csv
```

The resulting file opens correctly in Excel, Google Sheets, and Numbers without extra configuration. Timestamps are ISO 8601 strings from the provider, which most spreadsheet tools parse automatically.

## How do you export a specific date range?

A date-range export targets a fixed window rather than a rolling look-ahead from today. This is the right pattern for monthly reports, quarterly reviews, or auditing what was on the calendar during a past incident. The `--days` flag counts forward from the current date, so for a past range you'll want to use the JSON output and filter with jq's `select` on `when.start_time`. Export a wide window and filter down in post-processing — the CLI fetches quickly, and keeping the raw JSON lets you re-slice without another API call.

The example below exports 90 days, then filters to a specific month in jq. This pattern works for any fixed window: replace the `startswith` argument with the year-month prefix you need. The filtered CSV is smaller and easier to share with non-technical stakeholders.

```bash
# Export 90 days as JSON, then filter to a specific month
nylas calendar events list --days 90 --json > raw.json

# Filter to June 2026 and export as CSV
{
  echo 'title,start,end'
  jq -r '.[] | select(.when.start_time | startswith("2026-06")) |
    [(.title // ""), .when.start_time, (.when.end_time // "")] | @csv'
} < raw.json > june-2026.csv
```

## How do you export events from a specific calendar?

When a Google account has multiple calendars — a primary, a team, a shared room — each has a distinct calendar ID. Exporting events from a specific calendar means passing its ID to the events list command. The `nylas calendar list` command returns all calendars on the connected account, each with an `id` field. That ID is what you pass with `--calendar-id` to scope the export. A typical Google Workspace account has between 3 and 10 calendars; identifying the right one takes about 10 seconds.

This is useful for team-level exports (export only the shared engineering calendar), reporting (export only the customer-facing calendar), or backup (export each calendar to a separate file). You can loop over the output of `nylas calendar list` to produce one file per calendar automatically.

```bash
# Step 1: list available calendars and their IDs
nylas calendar list --json | jq -r '.[] | [.id, .name] | @tsv'

# Step 2: export a single calendar by ID
{
  echo 'title,start,end'
  nylas calendar events list --days 30 --json --calendar-id "cal_abc123"     | jq -r '.[] | [(.title // ""), .when.start_time, (.when.end_time // "")] | @csv'
} > team-calendar.csv

# Step 3: loop to export every calendar to its own file
nylas calendar list --json | jq -r '.[].id' | while read -r cal_id; do
  filename="export-${cal_id}.csv"
  {
    echo 'title,start,end'
    nylas calendar events list --days 30 --json --calendar-id "$cal_id"       | jq -r '.[] | [(.title // ""), .when.start_time, (.when.end_time // "")] | @csv'
  } > "$filename"
  echo "Wrote $filename"
done
```

## How do you set up an automated calendar backup?

An automated calendar backup runs the export on a schedule and saves the output to a timestamped file. A cron job or CI workflow handles the scheduling; the export command itself is deterministic and exits cleanly. Keeping timestamped files means you can diff two exports to see what changed between runs — useful for auditing recurring events, detecting deleted meetings, or tracking schedule changes over a sprint. A 90-day JSON export of a moderately active calendar runs in under 3 seconds on a typical connection.

The script below writes a timestamped JSON file and keeps the last 30 backups. Run it daily from cron or a GitHub Actions schedule trigger. The JSON format is the right choice for backup because it preserves every field; you can always derive CSV later from the JSON if reporting needs change.

```bash
#!/bin/bash
# backup-calendar.sh — run daily via cron or CI

set -euo pipefail

BACKUP_DIR="${HOME}/calendar-backups"
mkdir -p "$BACKUP_DIR"

TIMESTAMP=$(date +%Y-%m-%d)
OUTPUT="${BACKUP_DIR}/calendar-${TIMESTAMP}.json"

# Export 90 days of events
nylas calendar events list --days 90 --json > "$OUTPUT"

EVENT_COUNT=$(jq 'length' "$OUTPUT")
echo "Backed up ${EVENT_COUNT} events to ${OUTPUT}"

# Keep only the last 30 backup files
ls -t "$BACKUP_DIR"/calendar-*.json | tail -n +31 | xargs -r rm --
```

To verify a specific event after backup, use `nylas calendar events show` with the event ID from the JSON. This is faster than re-running a full export when you only need one record.

```bash
# Inspect a single event by its ID from the backup
EVENT_ID=$(jq -r '.[0].id' ~/calendar-backups/calendar-2026-06-09.json)
nylas calendar events show --id "$EVENT_ID" --json
```

## What causes incomplete or empty exports?

An empty export most often means the connected account doesn't have events in the requested window, or the grant ID belongs to an account with no calendars. Run `nylas calendar list` first to confirm the account has accessible calendars. If the list is empty, re-authenticate with `nylas auth login` and grant calendar read permissions during the OAuth flow. Google Calendar requires the `https://www.googleapis.com/auth/calendar.readonly` scope; the Nylas CLI requests it automatically during login.

A partial export — fewer events than expected — usually means the `--days` window is too short or the events are on a secondary calendar not covered by the default export. Use `--days 90` for a wider window, and check secondary calendars explicitly with `--calendar-id`. According to the [Nylas Calendar API documentation](https://developer.nylas.com/docs/v3/getting-started/calendar/), the default events list returns events from the primary calendar only when no calendar ID is specified.

Provider-side behavior for events created by others — shared calendars, room resources, or invites you haven't accepted — is documented to vary by provider. Verify locally if you expect these to appear in your export.

## Next steps

- [Manage calendar events from the terminal](https://cli.nylas.com/guides/manage-calendar-from-terminal) — create, update, and delete events from the same CLI
- [Calendar analytics from the terminal](https://cli.nylas.com/guides/calendar-analytics-cli) — group and count exported events for meeting-load reports
- [Extract email data with jq](https://cli.nylas.com/guides/extract-email-data-jq) — the same `@csv` and `select` patterns applied to email JSON
- [Export email to CSV from the terminal](https://cli.nylas.com/guides/email-to-csv-export) — RFC 4180 CSV export for email messages
- [Full command reference](https://cli.nylas.com/docs/commands) — every calendar flag and subcommand
