External Calendar API Reference
The Fusion Calling External Calendar API allows you to programmatically manage calendar events using API key authentication. This RESTful API provides full CRUD (Create, Read, Update, Delete) operations for calendar events, enabling seamless integration with automation tools, webhooks, and third-party applications.
https://app.fusioncalling.com/api/calendar/external/v1v1Authentication
All API requests require authentication using an API key. The API key must be included in the Authorization header using the Bearer token format.
Getting Your API Key
- Log in to your Fusion Calling account
- Navigate to Settings → API Keys
- Generate a new API key or use an existing one
- Copy the API key (it's only shown once when created)
Using Your API Key
Include the API key in the Authorization header of every request:
Authorization: Bearer your-api-key-hereExample:
curl -X GET "https://app.fusioncalling.com/api/calendar/external/v1/events" \
-H "Authorization: Bearer bf207bcf-c0de-4067-bd28-45728bd305aa"Endpoints
/api/calendar/external/v1/eventsRetrieve a list of events, optionally filtered by date range.
Authentication
Required
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
from | string | No | Filter events from this date (inclusive). Supports flexible datetime formats. |
to | string | No | Filter events until this date (inclusive). Supports flexible datetime formats. |
Request Example
curl -X GET "https://app.fusioncalling.com/api/calendar/external/v1/events?from=2025-12-01T00:00:00&to=2025-12-31T23:59:59" \
-H "Authorization: Bearer your-api-key-here"Response Example
1{
2 "success": true,
3 "data": [
4 {
5 "id": "550e8400-e29b-41d4-a716-446655440000",
6 "account_id": "account-uuid-here",
7 "user_id": "user-uuid-here",
8 "title": "Team Meeting",
9 "description": "Weekly team sync",
10 "start_time": "2025-12-15T14:30:00.000Z",
11 "end_time": "2025-12-15T16:00:00.000Z",
12 "all_day": false,
13 "source": "local",
14 "created_at": "2025-12-10T10:00:00.000Z",
15 "updated_at": "2025-12-10T10:00:00.000Z"
16 }
17 ]
18}Response Codes
/api/calendar/external/v1/events/{id}Retrieve a single event by its ID.
Authentication
Required
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (UUID) | Yes | The unique identifier of the event |
Request Example
curl -X GET "https://app.fusioncalling.com/api/calendar/external/v1/events/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer your-api-key-here"Response Example
1{
2 "success": true,
3 "data": {
4 "id": "550e8400-e29b-41d4-a716-446655440000",
5 "account_id": "account-uuid-here",
6 "user_id": "user-uuid-here",
7 "title": "Team Meeting",
8 "description": "Weekly team sync",
9 "start_time": "2025-12-15T14:30:00.000Z",
10 "end_time": "2025-12-15T16:00:00.000Z",
11 "all_day": false,
12 "source": "local",
13 "created_at": "2025-12-10T10:00:00.000Z",
14 "updated_at": "2025-12-10T10:00:00.000Z"
15 }
16}Response Codes
/api/calendar/external/v1/eventsCreate a new calendar event.
Authentication
Required
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Event title (1-255 characters) |
description | string | No | Event description (max 500 characters) |
start_time | string | Yes | Event start time (flexible datetime format) |
end_time | string | Yes | Event end time (flexible datetime format) |
all_day | boolean | No | Whether the event is all-day (default: false) |
Request Example
1curl -X POST "https://app.fusioncalling.com/api/calendar/external/v1/events" \
2 -H "Authorization: Bearer your-api-key-here" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "title": "Client Meeting",
6 "description": "Discuss project requirements",
7 "start_time": "2025-12-20T14:30:00",
8 "end_time": "2025-12-20T16:00:00",
9 "all_day": false
10 }'Response Example
1{
2 "success": true,
3 "data": {
4 "id": "770e8400-e29b-41d4-a716-446655440002",
5 "account_id": "account-uuid-here",
6 "user_id": "user-uuid-here",
7 "title": "Client Meeting",
8 "description": "Discuss project requirements",
9 "start_time": "2025-12-20T14:30:00.000Z",
10 "end_time": "2025-12-20T16:00:00.000Z",
11 "all_day": false,
12 "source": "local",
13 "created_at": "2025-12-11T10:00:00.000Z",
14 "updated_at": "2025-12-11T10:00:00.000Z"
15 }
16}Response Codes
Validation Errors
1{
2 "success": false,
3 "error": "Validation failed",
4 "details": {
5 "start_time": ["Invalid datetime format..."],
6 "end_time": ["Invalid datetime format..."],
7 "title": ["Title is required"]
8 }
9}/api/calendar/external/v1/events/{id}Update an existing event. All fields are optional - only provided fields will be updated.
Authentication
Required
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (UUID) | Yes | The unique identifier of the event |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
title | string | No | Event title (1-255 characters) |
description | string | No | Event description (max 500 characters). Use null to clear. |
start_time | string | No | Event start time (flexible datetime format) |
end_time | string | No | Event end time (flexible datetime format) |
all_day | boolean | No | Whether the event is all-day |
Request Example
1curl -X PATCH "https://app.fusioncalling.com/api/calendar/external/v1/events/550e8400-e29b-41d4-a716-446655440000" \
2 -H "Authorization: Bearer your-api-key-here" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "title": "Updated Meeting Title",
6 "description": "Updated description",
7 "start_time": "2025-12-15T15:00:00",
8 "end_time": "2025-12-15T17:00:00"
9 }'Response Example
1{
2 "success": true,
3 "data": {
4 "id": "550e8400-e29b-41d4-a716-446655440000",
5 "account_id": "account-uuid-here",
6 "user_id": "user-uuid-here",
7 "title": "Updated Meeting Title",
8 "description": "Updated description",
9 "start_time": "2025-12-15T15:00:00.000Z",
10 "end_time": "2025-12-15T17:00:00.000Z",
11 "all_day": false,
12 "source": "local",
13 "created_at": "2025-12-10T10:00:00.000Z",
14 "updated_at": "2025-12-11T11:30:00.000Z"
15 }
16}Response Codes
/api/calendar/external/v1/events/{id}Delete an event by its ID.
Authentication
Required
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (UUID) | Yes | The unique identifier of the event |
Request Example
curl -X DELETE "https://app.fusioncalling.com/api/calendar/external/v1/events/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer your-api-key-here"Response Example
{
"success": true,
"message": "Event deleted successfully"
}Response Codes
Data Models
Event Object
1interface Event {
2 id: string; // UUID
3 account_id: string; // UUID - Account this event belongs to
4 user_id: string; // UUID - User who created the event
5 title: string; // 1-255 characters
6 description: string | null; // Max 500 characters, nullable
7 start_time: string; // ISO 8601 datetime (normalized)
8 end_time: string; // ISO 8601 datetime (normalized)
9 all_day: boolean; // Whether event is all-day
10 source: string; // Source of event (e.g., "local")
11 created_at: string; // ISO 8601 datetime
12 updated_at: string; // ISO 8601 datetime
13}Datetime Formats
The API accepts flexible datetime formats and automatically normalizes them to ISO 8601 for storage.
Supported Formats
All of these formats are accepted:
1. Simple Format (recommended):
2025-12-15T14:30:00No milliseconds/timezone (assumes UTC)
2. ISO 8601 Without Milliseconds:
2025-12-15T14:30:00ZUTC timezone specified
3. Full ISO 8601 (RFC 3339):
2025-12-15T14:30:00.000Z2025-12-15T14:30:00.123ZWith milliseconds and fractional seconds
4. With Timezone Offset:
2025-12-15T14:30:00+05:302025-12-15T14:30:00-08:00IST and PST timezones
5. Space Separator:
2025-12-15 14:30:00Space instead of T (assumes UTC)
6. Other JavaScript Date Formats:
Any format parseable by JavaScript's Date() constructor
Normalization
All datetime values are automatically normalized to ISO 8601 format with milliseconds and UTC timezone:
2025-12-15T14:30:002025-12-15T14:30:00.000ZResponses always return dates in normalized ISO 8601 format.
Error Handling
Error Response Format
All error responses follow this structure:
1{
2 "success": false,
3 "error": "Error message",
4 "details": {
5 // Optional: Field-specific errors for validation
6 }
7}HTTP Status Codes
| Code | Meaning | Description |
|---|---|---|
200 | OK | Request successful |
201 | Created | Resource created successfully |
400 | Bad Request | Validation error or invalid parameters |
401 | Unauthorized | Invalid or missing API key |
404 | Not Found | Resource not found or doesn't belong to your account |
500 | Internal Server Error | Server error |
Common Errors
401 Unauthorized
{
"error": "Unauthorized",
"message": "Invalid or missing API key"
}Solution: Check that your API key is correct and included in the Authorization header.
400 Validation Error
1{
2 "success": false,
3 "error": "Validation failed",
4 "details": {
5 "start_time": ["Invalid datetime format. Supported formats: ..."],
6 "title": ["Title is required"],
7 "end_time": ["End time must be after start time"]
8 }
9}Solution: Check the validation errors in the details object and correct your request.
404 Not Found
{
"error": "Event not found"
}Solution: Verify the event ID is correct and belongs to your account.
429 Rate Limit Exceeded
1{
2 "error": "Rate limit exceeded",
3 "message": "Too many requests. Limit: 12 requests per minute.",
4 "retryAfter": 45,
5 "limit": 12,
6 "remaining": 0
7}Solution: Wait for the duration specified in retryAfter (in seconds) before making another request. Check the X-RateLimit-Reset header to know when the rate limit window resets.
Rate Limiting
The External Calendar API implements rate limiting to protect the service from abuse and ensure fair usage.
Rate Limit Details
- Limit: 12 requests per minute per API key
- Window: Sliding window (last 60 seconds)
- Scope: Per API key (each key has independent limits)
Rate Limit Headers
All API responses include rate limit headers:
X-RateLimit-Limit: Maximum number of requests allowed (12)X-RateLimit-Remaining: Number of requests remaining in the current windowX-RateLimit-Reset: Unix timestamp when the rate limit resetsRetry-After: Number of seconds to wait before retrying (only on 429 responses)
Best Practices
- Monitor Rate Limit Headers: Check
X-RateLimit-Remainingto avoid hitting the limit - Implement Exponential Backoff: If you receive a 429 response, wait for the
Retry-Afterduration before retrying - Batch Operations: When possible, batch multiple operations to reduce API calls
- Cache Responses: Cache API responses when appropriate to reduce unnecessary requests
Code Examples
JavaScript/TypeScript (Fetch API)
1const API_KEY = "your-api-key-here";
2const BASE_URL = "https://app.fusioncalling.com/api/calendar/external/v1";
3
4// List events
5async function listEvents(from, to) {
6 const params = new URLSearchParams();
7 if (from) params.append("from", from);
8 if (to) params.append("to", to);
9
10 const response = await fetch(`${BASE_URL}/events?${params}`, {
11 method: "GET",
12 headers: {
13 Authorization: `Bearer ${API_KEY}`,
14 },
15 });
16
17 return await response.json();
18}
19
20// Create event
21async function createEvent(eventData) {
22 const response = await fetch(`${BASE_URL}/events`, {
23 method: "POST",
24 headers: {
25 Authorization: `Bearer ${API_KEY}`,
26 "Content-Type": "application/json",
27 },
28 body: JSON.stringify(eventData),
29 });
30
31 return await response.json();
32}
33
34// Update event
35async function updateEvent(eventId, updates) {
36 const response = await fetch(`${BASE_URL}/events/${eventId}`, {
37 method: "PATCH",
38 headers: {
39 Authorization: `Bearer ${API_KEY}`,
40 "Content-Type": "application/json",
41 },
42 body: JSON.stringify(updates),
43 });
44
45 return await response.json();
46}
47
48// Delete event
49async function deleteEvent(eventId) {
50 const response = await fetch(`${BASE_URL}/events/${eventId}`, {
51 method: "DELETE",
52 headers: {
53 Authorization: `Bearer ${API_KEY}`,
54 },
55 });
56
57 return await response.json();
58}
59
60// Example usage
61(async () => {
62 // Create an event
63 const newEvent = await createEvent({
64 title: "Team Standup",
65 description: "Daily sync meeting",
66 start_time: "2025-12-15T09:00:00",
67 end_time: "2025-12-15T09:30:00",
68 all_day: false,
69 });
70 console.log("Created:", newEvent);
71
72 // List events
73 const events = await listEvents("2025-12-01T00:00:00", "2025-12-31T23:59:59");
74 console.log("Events:", events);
75
76 // Update event
77 if (newEvent.success) {
78 const updated = await updateEvent(newEvent.data.id, {
79 title: "Updated Standup",
80 start_time: "2025-12-15T09:15:00",
81 });
82 console.log("Updated:", updated);
83 }
84})();Python (requests)
1import requests
2from datetime import datetime
3
4API_KEY = 'your-api-key-here'
5BASE_URL = 'https://app.fusioncalling.com/api/calendar/external/v1'
6
7headers = {
8 'Authorization': f'Bearer {API_KEY}',
9 'Content-Type': 'application/json',
10}
11
12# List events
13def list_events(from_date=None, to_date=None):
14 params = {}
15 if from_date:
16 params['from'] = from_date
17 if to_date:
18 params['to'] = to_date
19
20 response = requests.get(f'{BASE_URL}/events', headers=headers, params=params)
21 return response.json()
22
23# Create event
24def create_event(title, description, start_time, end_time, all_day=False):
25 data = {
26 'title': title,
27 'description': description,
28 'start_time': start_time,
29 'end_time': end_time,
30 'all_day': all_day,
31 }
32 response = requests.post(f'{BASE_URL}/events', headers=headers, json=data)
33 return response.json()
34
35# Update event
36def update_event(event_id, **updates):
37 response = requests.patch(
38 f'{BASE_URL}/events/{event_id}',
39 headers=headers,
40 json=updates
41 )
42 return response.json()
43
44# Delete event
45def delete_event(event_id):
46 response = requests.delete(
47 f'{BASE_URL}/events/{event_id}',
48 headers=headers
49 )
50 return response.json()
51
52# Example usage
53if __name__ == '__main__':
54 # Create an event
55 new_event = create_event(
56 title='Team Standup',
57 description='Daily sync meeting',
58 start_time='2025-12-15T09:00:00',
59 end_time='2025-12-15T09:30:00',
60 all_day=False
61 )
62 print('Created:', new_event)
63
64 # List events
65 events = list_events(
66 from_date='2025-12-01T00:00:00',
67 to_date='2025-12-31T23:59:59'
68 )
69 print('Events:', events)
70
71 # Update event
72 if new_event.get('success'):
73 updated = update_event(
74 new_event['data']['id'],
75 title='Updated Standup',
76 start_time='2025-12-15T09:15:00'
77 )
78 print('Updated:', updated)cURL Examples
1# Set your API key
2API_KEY="your-api-key-here"
3BASE_URL="https://app.fusioncalling.com/api/calendar/external/v1"
4
5# List events
6curl -X GET "${BASE_URL}/events?from=2025-12-01T00:00:00&to=2025-12-31T23:59:59" \
7 -H "Authorization: Bearer ${API_KEY}"
8
9# Create event
10curl -X POST "${BASE_URL}/events" \
11 -H "Authorization: Bearer ${API_KEY}" \
12 -H "Content-Type: application/json" \
13 -d '{
14 "title": "Team Meeting",
15 "description": "Weekly sync",
16 "start_time": "2025-12-15T14:30:00",
17 "end_time": "2025-12-15T16:00:00",
18 "all_day": false
19 }'
20
21# Get event
22curl -X GET "${BASE_URL}/events/550e8400-e29b-41d4-a716-446655440000" \
23 -H "Authorization: Bearer ${API_KEY}"
24
25# Update event
26curl -X PATCH "${BASE_URL}/events/550e8400-e29b-41d4-a716-446655440000" \
27 -H "Authorization: Bearer ${API_KEY}" \
28 -H "Content-Type: application/json" \
29 -d '{
30 "title": "Updated Meeting Title"
31 }'
32
33# Delete event
34curl -X DELETE "${BASE_URL}/events/550e8400-e29b-41d4-a716-446655440000" \
35 -H "Authorization: Bearer ${API_KEY}"Best Practices
1. API Key Security
- Never expose API keys in client-side code or public repositories
- Store API keys in environment variables or secure key management systems
- Rotate API keys regularly for security
- Revoke unused keys to minimize attack surface
2. Datetime Handling
- Use the simple format (
2025-12-15T14:30:00) for ease of use - Always specify times in UTC when possible to avoid timezone issues
- For all-day events, set
start_timeto00:00:00andend_timeto23:59:59
3. Error Handling
- Always check the
successfield in responses - Handle
401errors by verifying your API key - Validate user input before sending requests
- Implement retry logic for
500errors with exponential backoff
4. Performance
- Use date range filters when listing events to reduce response size
- Cache event data when appropriate
- Batch operations when possible (future feature)
5. Data Validation
- Validate
end_time > start_timebefore creating/updating events - Ensure title length is between 1-255 characters
- Keep descriptions under 500 characters
6. Account Isolation
- Remember that API keys are scoped to your account
- You can only access events belonging to your account
- Event IDs from other accounts will return
404 Not Found
Support
For API support, please contact:
Email: hello@fusioncalling.com
Documentation: Check our docs folder for additional resources
Changelog
Version 1.0 (Current)
- Initial API release
- Support for CRUD operations on calendar events
- Flexible datetime format support
- API key authentication
- Account-scoped data access
Last updated: December 2025