Calendar API Reference
Complete API reference for Solo's calendar system.
Base URL
https://solomail.io/api/v1/calendar
Authentication
All endpoints require API key authentication:
Authorization: Bearer <your-api-key>
Events
Create Event
Create a new calendar event.
Endpoint: POST /events
Request Body:
{ "title": "Team Standup", "description": "Daily standup meeting", "startTime": "2026-01-20T09:00:00-05:00", "endTime": "2026-01-20T09:30:00-05:00", "timezone": "America/New_York", "allDay": false, "location": "Conference Room A", "virtualMeeting": { "provider": "zoom", "url": "https://zoom.us/j/123456789", "password": "abc123" }, "color": "blue", "recurrence": "weekly", "recurrenceEndDate": "2026-06-01T00:00:00Z", "agentId": "agent-uuid", "sendEmailReminders": true, "reminders": [ { "type": "email", "value": 15, "unit": "minutes" } ], "invitees": [ { "email": "john@example.com", "name": "John Doe", "isOptional": false } ] }
Request Fields:
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Event title |
description | string | No | Event description |
startTime | string | Yes | ISO 8601 start time |
endTime | string | Yes | ISO 8601 end time |
timezone | string | No | IANA timezone (default: "UTC") |
allDay | boolean | No | All-day event flag (default: false) |
location | string | No | Physical location |
virtualMeeting | object | No | Video conference details |
color | string | No | blue, green, red, purple, orange |
recurrence | string | No | none, daily, weekly, biweekly, monthly, yearly |
recurrenceEndDate | string | No | ISO 8601 end date for recurrence |
agentId | string | No | Agent UUID for branded invites |
sendEmailReminders | boolean | No | Send invitation emails (default: true) |
reminders | array | No | Reminder settings |
invitees | array | No | Event invitees |
Response (201 Created):
{ "success": true, "event": { "id": "event-uuid", "identityId": "identity-uuid", "title": "Team Standup", "description": "Daily standup meeting", "startTime": "2026-01-20T14:00:00.000Z", "endTime": "2026-01-20T14:30:00.000Z", "timezone": "America/New_York", "allDay": false, "location": "Conference Room A", "virtualMeeting": { ... }, "color": "blue", "recurrence": "weekly", "status": "confirmed", "sendEmailReminders": true, "agentId": "agent-uuid", "invitees": [ ... ], "agent": { "id": "...", "name": "...", "avatarUrl": "..." }, "createdAt": "2026-01-16T12:00:00.000Z", "updatedAt": "2026-01-16T12:00:00.000Z" } }
List Events
Get calendar events with optional filtering.
Endpoint: GET /events
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
startDate | string | ISO 8601 date - filter events ending after this date |
endDate | string | ISO 8601 date - filter events starting before this date |
agentId | string | Filter by associated agent UUID |
includeInvitees | boolean | Include invitee details (default: false) |
limit | number | Max results (default: 500) |
Example Requests:
# Get events for January 2026 GET /events?startDate=2026-01-01&endDate=2026-01-31&includeInvitees=true # Get events for a specific agent GET /events?agentId=agent-uuid&includeInvitees=true # Get next 10 events GET /events?startDate=2026-01-16&limit=10
Response (200 OK):
{ "events": [ { "id": "event-uuid", "title": "Team Standup", "startTime": "2026-01-20T14:00:00.000Z", "endTime": "2026-01-20T14:30:00.000Z", "timezone": "America/New_York", "allDay": false, "color": "blue", "status": "confirmed", "invitees": [ ... ], "agent": { ... } } ], "count": 1 }
Get Event
Get a single event by ID.
Endpoint: GET /events/{eventId}
Response (200 OK):
{ "event": { "id": "event-uuid", "title": "Team Standup", "description": "Daily standup meeting", "startTime": "2026-01-20T14:00:00.000Z", "endTime": "2026-01-20T14:30:00.000Z", "timezone": "America/New_York", "allDay": false, "location": "Conference Room A", "virtualMeeting": { ... }, "color": "blue", "recurrence": "weekly", "status": "confirmed", "sendEmailReminders": true, "agentId": "agent-uuid", "invitees": [ { "id": "invitee-uuid", "email": "john@example.com", "name": "John Doe", "responseStatus": "accepted", "isOrganizer": false, "isOptional": false } ], "agent": { "id": "...", "name": "...", "avatarUrl": "..." }, "createdAt": "2026-01-16T12:00:00.000Z", "updatedAt": "2026-01-16T12:00:00.000Z" } }
Update Event
Update an existing event. Supports partial updates.
Endpoint: PATCH /events/{eventId}
Request Body:
{ "title": "Updated: Team Standup", "startTime": "2026-01-20T10:00:00-05:00", "endTime": "2026-01-20T10:30:00-05:00", "agentId": "new-agent-uuid", "invitees": [ { "email": "john@example.com", "name": "John Doe" }, { "email": "newperson@example.com", "name": "New Person" } ], "notifyAttendeesOfChanges": true }
Additional Request Fields:
| Field | Type | Description |
|---|---|---|
status | string | confirmed, tentative, cancelled |
notifyAttendeesOfChanges | boolean | Send update emails to ALL invitees |
Update Email Behavior:
| Scenario | Email Behavior |
|---|---|
| Add new invitees only | New invitees receive invitation emails |
notifyAttendeesOfChanges: true | ALL invitees receive update emails |
notifyAttendeesOfChanges: false | Only new invitees receive emails |
Response (200 OK):
{ "success": true, "event": { /* updated event object */ } }
Delete Event
Delete an event.
Endpoint: DELETE /events/{eventId}
Response (200 OK):
{ "success": true }
Note: Deleting an event does not automatically send cancellation emails. To notify invitees, update the event with status: "cancelled" and notifyAttendeesOfChanges: true before deleting.
RSVP
Respond to Invitation
Respond to a calendar invitation (for invitees with Solo accounts).
Endpoint: POST /events/{eventId}/rsvp
Request Body:
{ "response": "accepted" }
Response Values: accepted, declined, tentative
Response (200 OK):
{ "success": true }
Availability
Check Availability
Check free/busy status for a time range.
Endpoint: GET /availability
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
startTime | string | Yes | ISO 8601 start time |
endTime | string | Yes | ISO 8601 end time |
excludeEventId | string | No | Exclude this event from conflict check |
Response (200 OK):
{ "available": false, "conflicts": [ { "id": "conflict-event-uuid", "title": "Existing Meeting", "startTime": "2026-01-20T09:00:00.000Z", "endTime": "2026-01-20T10:00:00.000Z" } ] }
Object Schemas
Virtual Meeting
{ "provider": "zoom" | "google_meet" | "teams" | "custom", "url": "https://...", "password": "optional" }
Reminder
{ "type": "email", "value": 15, "unit": "minutes" | "hours" | "days" }
Invitee (Request)
{ "email": "invitee@example.com", "name": "Display Name", "isOptional": false }
Invitee (Response)
{ "id": "invitee-uuid", "email": "invitee@example.com", "name": "Display Name", "responseStatus": "needs_action" | "accepted" | "declined" | "tentative", "isOrganizer": false, "isOptional": false }
Error Responses
400 Bad Request
{ "success": false, "error": "End time must be after start time" }
404 Not Found
{ "success": false, "error": "Event not found" }
401 Unauthorized
{ "error": "Unauthorized", "message": "Invalid or expired API key" }
Examples
Create Event with cURL
curl -X POST https://solomail.io/api/v1/calendar/events \ -H "Authorization: Bearer sk_live_YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "Client Call", "startTime": "2026-01-20T15:00:00-05:00", "endTime": "2026-01-20T16:00:00-05:00", "timezone": "America/New_York", "sendEmailReminders": true, "invitees": [ { "email": "client@example.com", "name": "Client Name" } ] }'
Update Event Time
curl -X PATCH https://solomail.io/api/v1/calendar/events/event-uuid \ -H "Authorization: Bearer sk_live_YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "startTime": "2026-01-20T16:00:00-05:00", "endTime": "2026-01-20T17:00:00-05:00", "notifyAttendeesOfChanges": true }'
Check Availability
curl "https://solomail.io/api/v1/calendar/availability?startTime=2026-01-20T15:00:00Z&endTime=2026-01-20T16:00:00Z" \ -H "Authorization: Bearer sk_live_YOUR_API_KEY"
Version: 1.0.0
Last Updated: January 2026