Guide
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 Director of Product Management
Command references used in this guide: nylas calendar events list, nylas calendar list, and nylas 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.
# 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 eventHow 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, 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 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.
# 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.csvThe 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.
# 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.csvHow 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.
# 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"
doneHow 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.
#!/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.
# 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" --jsonWhat 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, 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 — create, update, and delete events from the same CLI
- Calendar analytics from the terminal — group and count exported events for meeting-load reports
- Extract email data with jq — the same
@csvandselectpatterns applied to email JSON - Export email to CSV from the terminal — RFC 4180 CSV export for email messages
- Full command reference — every calendar flag and subcommand