API Documentation
Build AI agents and integrations with the Intervals API.
Base URL: https://intervals.so/api/v1
Authentication
All API requests require an API key in the Authorization header:
Authorization: Bearer ivl_live_xxxxxxxxxxxxxGenerate API keys in your dashboard → Settings → API Keys.
Rate Limits
Pro tier
1,000 requests/day
Free trial
100 requests/day
Error Handling
All errors return a consistent JSON format:
{
"error": "Human-readable error message",
"message": "Additional details (optional)",
"details": [...] // Validation errors only
}Common Error Codes
400Bad Request — Invalid parameters or missing required fields401Unauthorized — Invalid or missing API key403Forbidden — API access not available for your tier404Not Found — Resource doesn't exist429Too Many Requests — Rate limit exceeded500Internal Server Error — Something went wrongProfile
/profileGet your profile information
Request
curl https://intervals.so/api/v1/profile \
-H "Authorization: Bearer ivl_live_..."Response
{
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Ruzgar",
"timezone": "Europe/Tallinn",
"subscription_tier": "pro",
"calendar_connected": true,
"default_duration": 30,
"api_key_name": "My AI Assistant"
}Response Fields
user_id(string)— Your unique user IDname(string)— Display nametimezone(string)— IANA timezone (e.g., "Europe/Tallinn")subscription_tier(string)— "free", "beta", or "pro"calendar_connected(boolean)— Whether Google Calendar is connecteddefault_duration(number)— Default meeting duration in minutesapi_key_name(string)— Name of the API key used for this requestAvailability
/availabilityCheck availability for a specific date
Query Parameters
date(string)required— Date in YYYY-MM-DD formatRequest
curl "https://intervals.so/api/v1/availability?date=2026-02-06" \
-H "Authorization: Bearer ivl_live_..."Response
{
"date": "2026-02-06",
"timezone": "Europe/Tallinn",
"day_of_week": "friday",
"working_hours": {
"start": "09:00",
"end": "17:00"
},
"intervals": [
{ "title": "Friday afternoon", "time_range": "13:00 – 17:00" }
],
"busy_slots": [
{ "start": "14:00", "end": "14:30", "title": "Team Standup" }
],
"available_slots": [
{ "start": "13:00", "end": "14:00" },
{ "start": "14:30", "end": "17:00" }
]
}Response Fields
date(string)— The requested datetimezone(string)— User timezoneday_of_week(string)— Day name (lowercase)working_hours(object)— Overall working window for the dayintervals(array)— Active availability intervals for this daybusy_slots(array)— Calendar events blocking timeavailable_slots(array)— Free time windows/availability/slotsGet bookable time slots for a date range. Ideal for AI agents finding meeting times.
Query Parameters
start(string)required— Start date (YYYY-MM-DD)end(string)required— End date (YYYY-MM-DD), max 14 days from startduration(number)— Meeting duration in minutes (default: user setting)buffer_before(number)— Buffer before meeting in minutes (default: 15)buffer_after(number)— Buffer after meeting in minutes (default: 15)limit(number)— Max slots to return (default: 10, max: 50)Request
curl "https://intervals.so/api/v1/availability/slots?start=2026-02-06&end=2026-02-10&duration=30&limit=5" \
-H "Authorization: Bearer ivl_live_..."Response
{
"timezone": "Europe/Tallinn",
"duration_minutes": 30,
"buffer_before_minutes": 15,
"buffer_after_minutes": 15,
"date_range": { "start": "2026-02-06", "end": "2026-02-10" },
"total_slots": 5,
"slots": [
{
"date": "2026-02-06",
"start": "13:00",
"end": "13:30",
"iso_start": "2026-02-06T11:00:00.000Z",
"iso_end": "2026-02-06T11:30:00.000Z"
},
{
"date": "2026-02-06",
"start": "15:00",
"end": "15:30",
"iso_start": "2026-02-06T13:00:00.000Z",
"iso_end": "2026-02-06T13:30:00.000Z"
}
]
}Response Fields
slots[].date(string)— Date of the slot (YYYY-MM-DD)slots[].start(string)— Start time in local timezone (HH:MM)slots[].end(string)— End time in local timezone (HH:MM)slots[].iso_start(string)— Start time in ISO 8601 UTCslots[].iso_end(string)— End time in ISO 8601 UTCCalendar Events
/eventsList calendar events for a date range
Query Parameters
start(string)required— Start date (YYYY-MM-DD)end(string)required— End date (YYYY-MM-DD), max 30 days from startinclude_all_day(boolean)— Include all-day events (default: true)Request
curl "https://intervals.so/api/v1/events?start=2026-02-06&end=2026-02-06" \
-H "Authorization: Bearer ivl_live_..."Response
{
"timezone": "Europe/Tallinn",
"date_range": { "start": "2026-02-06", "end": "2026-02-06" },
"total_events": 2,
"events": [
{
"id": "abc123xyz",
"title": "Team Standup",
"start": "2026-02-06T09:00:00+02:00",
"end": "2026-02-06T09:30:00+02:00",
"all_day": false,
"description": "Daily sync",
"attendees": ["alice@example.com", "bob@example.com"],
"meet_link": "https://meet.google.com/abc-def-ghi",
"status": "confirmed",
"is_recurring": true,
"is_intervals_event": false
}
]
}Response Fields
events[].id(string)— Unique event ID (use for PATCH/DELETE)events[].title(string)— Event titleevents[].start(string)— Start time (ISO 8601 with timezone)events[].end(string)— End time (ISO 8601 with timezone)events[].all_day(boolean)— Whether this is an all-day eventevents[].attendees(string[])— List of attendee emailsevents[].meet_link(string | null)— Google Meet link if presentevents[].status(string)— "confirmed", "tentative", or "cancelled"events[].is_intervals_event(boolean)— Whether created via Intervals/eventsCreate a new calendar event
Request Body
title(string)required— Event titlestart(string)required— Start time (ISO 8601)end(string)required— End time (ISO 8601)description(string)— Event descriptionattendee_email(string)— Guest email (adds Google Meet link)Request
curl -X POST "https://intervals.so/api/v1/events" \
-H "Authorization: Bearer ivl_live_..." \
-H "Content-Type: application/json" \
-d '{
"title": "Coffee Chat with Sarah",
"start": "2026-02-07T14:00:00Z",
"end": "2026-02-07T14:30:00Z",
"attendee_email": "sarah@example.com"
}'Response
{
"success": true,
"event": {
"id": "event123abc",
"title": "Coffee Chat with Sarah",
"start": "2026-02-07T14:00:00.000Z",
"end": "2026-02-07T14:30:00.000Z",
"meet_link": "https://meet.google.com/xyz-abc-123"
}
}/events/:idUpdate an existing calendar event. Only provided fields are updated.
Request Body
title(string)— New event titlestart(string)— New start time (ISO 8601)end(string)— New end time (ISO 8601)description(string)— New descriptionRequest
curl -X PATCH "https://intervals.so/api/v1/events/abc123xyz" \
-H "Authorization: Bearer ivl_live_..." \
-H "Content-Type: application/json" \
-d '{
"title": "Updated: Coffee Chat",
"start": "2026-02-07T15:00:00Z",
"end": "2026-02-07T15:30:00Z"
}'Response
{
"success": true,
"event": {
"id": "abc123xyz",
"title": "Updated: Coffee Chat",
"start": "2026-02-07T15:00:00.000Z",
"end": "2026-02-07T15:30:00.000Z"
}
}Errors
400— At least one field must be provided404— Event not found/events/:idCancel/delete a calendar event. Attendees are notified of cancellation.
Request
curl -X DELETE "https://intervals.so/api/v1/events/abc123xyz" \
-H "Authorization: Bearer ivl_live_..."Response
{
"success": true,
"event_id": "abc123xyz",
"message": "Event cancelled successfully"
}Errors
404— Event not foundTasks
/tasksList all tasks with optional filters
Query Parameters
status(string)— "pending", "completed", or "dropped"priority(string)— "low", "medium", "high", or "urgent"due_date(string)— Filter by due date (YYYY-MM-DD)limit(number)— Max results (default: 50, max: 100)offset(number)— Pagination offset (default: 0)sort(string)— Sort field, prefix with - for desc (e.g., "-priority", "due_date")Request
curl "https://intervals.so/api/v1/tasks?status=pending&priority=high" \
-H "Authorization: Bearer ivl_live_..."Response
{
"tasks": [
{
"id": "task-uuid-123",
"title": "Ship API documentation",
"description": "Complete API docs with examples",
"status": "pending",
"priority": "high",
"due_date": "2026-02-06",
"created_at": "2026-02-05T10:00:00Z",
"completed_at": null
}
],
"total": 1,
"limit": 50,
"offset": 0
}Response Fields
tasks[].id(string)— Unique task ID (UUID)tasks[].title(string)— Task titletasks[].description(string | null)— Task descriptiontasks[].status(string)— "pending", "completed", or "dropped"tasks[].priority(string)— "low", "medium", "high", or "urgent"tasks[].due_date(string | null)— Due date (YYYY-MM-DD) or nulltasks[].completed_at(string | null)— Completion timestamp or null/tasks/todayGet today's tasks (due today + overdue + no due date)
Query Parameters
include_overdue(boolean)— Include overdue tasks (default: true)Request
curl "https://intervals.so/api/v1/tasks/today" \
-H "Authorization: Bearer ivl_live_..."Response
{
"date": "2026-02-06",
"timezone": "Europe/Tallinn",
"total": 3,
"tasks": [...],
"categorized": {
"due_today": [...],
"overdue": [...],
"no_due_date": [...]
}
}/tasksCreate a new task
Request Body
title(string)required— Task titledescription(string)— Task descriptionpriority(string)— "low", "medium" (default), "high", or "urgent"due_date(string)— Due date (YYYY-MM-DD)Request
curl -X POST "https://intervals.so/api/v1/tasks" \
-H "Authorization: Bearer ivl_live_..." \
-H "Content-Type: application/json" \
-d '{
"title": "Review pull request",
"priority": "high",
"due_date": "2026-02-06"
}'Response
{
"task": {
"id": "task-uuid-456",
"title": "Review pull request",
"description": null,
"status": "pending",
"priority": "high",
"due_date": "2026-02-06",
"created_at": "2026-02-06T10:00:00Z",
"completed_at": null
}
}/tasks/:idUpdate a task
Request Body
title(string)— New titledescription(string)— New descriptionstatus(string)— "pending", "completed", or "dropped"priority(string)— "low", "medium", "high", or "urgent"due_date(string)— Due date (YYYY-MM-DD) or null to clearRequest
curl -X PATCH "https://intervals.so/api/v1/tasks/task-uuid-456" \
-H "Authorization: Bearer ivl_live_..." \
-H "Content-Type: application/json" \
-d '{"status": "completed"}'Response
{
"task": {
"id": "task-uuid-456",
"title": "Review pull request",
"status": "completed",
"completed_at": "2026-02-06T12:00:00Z",
...
}
}/tasks/:id/completeMark a task as completed (shortcut for PATCH with status=completed)
Request
curl -X POST "https://intervals.so/api/v1/tasks/task-uuid-456/complete" \
-H "Authorization: Bearer ivl_live_..."Response
{
"task": { ... },
"message": "Task marked as completed"
}/tasks/:idDelete a task permanently
Request
curl -X DELETE "https://intervals.so/api/v1/tasks/task-uuid-456" \
-H "Authorization: Bearer ivl_live_..."Response
{
"success": true,
"message": "Task deleted successfully"
}Intervals (Availability Windows)
/intervalsList your availability intervals
Query Parameters
active_only(boolean)— Only return active intervals (default: true)Request
curl "https://intervals.so/api/v1/intervals" \
-H "Authorization: Bearer ivl_live_..."Response
{
"timezone": "Europe/Tallinn",
"default_duration": 30,
"total_intervals": 2,
"intervals": [
{
"id": "interval-uuid-1",
"title": "Weekday mornings",
"time_range": "9:00 – 12:00",
"is_active": true,
"days": ["monday", "tuesday", "wednesday", "thursday", "friday"],
"start_time": "09:00",
"end_time": "12:00"
},
{
"id": "interval-uuid-2",
"title": "Friday afternoon",
"time_range": "14:00 – 17:00",
"is_active": true,
"days": ["friday"],
"start_time": "14:00",
"end_time": "17:00"
}
]
}/intervalsCreate a new availability interval
Request Body
title(string)required— Name with day info (e.g., "Monday morning", "Weekday afternoons")time_range(string)required— Time range in "HH:MM – HH:MM" formatRequest
curl -X POST "https://intervals.so/api/v1/intervals" \
-H "Authorization: Bearer ivl_live_..." \
-H "Content-Type: application/json" \
-d '{
"title": "Saturday morning",
"time_range": "10:00 – 13:00"
}'Response
{
"success": true,
"interval": {
"id": "interval-uuid-3",
"title": "Saturday morning",
"time_range": "10:00 – 13:00",
"is_active": true
}
}Agent Discovery
For AI agent-to-agent meeting scheduling. See our IANP Protocol docs for full details.
/agent/discoverDiscover a user for meeting negotiation
Query Parameters
key(string)— Public agent key (ivl_pub_xxx) - preferredusername(string)— Username - alternative to keyRequest
curl "https://intervals.so/api/v1/agent/discover?key=ivl_pub_abc123" \
-H "Authorization: Bearer ivl_live_..."Response
{
"found": true,
"user": {
"public_key": "ivl_pub_abc123",
"username": "ruzgar",
"display_name": "Ruzgar"
},
"negotiation_endpoint": "https://intervals.so/api/v1/agent-negotiation",
"protocol": {
"name": "IANP",
"version": "1.0"
}
}Need help with the API?
hello@intervals.so