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.

Base URL:https://app.fusioncalling.com/api/calendar/external/v1
API Version:v1

Authentication

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

  1. Log in to your Fusion Calling account
  2. Navigate to Settings → API Keys
  3. Generate a new API key or use an existing one
  4. 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-here

Example:

curl -X GET "https://app.fusioncalling.com/api/calendar/external/v1/events" \
  -H "Authorization: Bearer bf207bcf-c0de-4067-bd28-45728bd305aa"

Endpoints

GET/api/calendar/external/v1/events

Retrieve a list of events, optionally filtered by date range.

Authentication

Required

Query Parameters

ParameterTypeRequiredDescription
fromstringNoFilter events from this date (inclusive). Supports flexible datetime formats.
tostringNoFilter 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

200Success
401Invalid or missing API key
400Invalid date format in query parameters
500Server error
GET/api/calendar/external/v1/events/{id}

Retrieve a single event by its ID.

Authentication

Required

Path Parameters

ParameterTypeRequiredDescription
idstring (UUID)YesThe 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

200Success
401Invalid or missing API key
404Event not found or doesn't belong to your account
500Server error
POST/api/calendar/external/v1/events

Create a new calendar event.

Authentication

Required

Request Body

FieldTypeRequiredDescription
titlestringYesEvent title (1-255 characters)
descriptionstringNoEvent description (max 500 characters)
start_timestringYesEvent start time (flexible datetime format)
end_timestringYesEvent end time (flexible datetime format)
all_daybooleanNoWhether 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

201Event created successfully
400Validation error (see error details)
401Invalid or missing API key
500Server error

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}
PATCH/api/calendar/external/v1/events/{id}

Update an existing event. All fields are optional - only provided fields will be updated.

Authentication

Required

Path Parameters

ParameterTypeRequiredDescription
idstring (UUID)YesThe unique identifier of the event

Request Body

FieldTypeRequiredDescription
titlestringNoEvent title (1-255 characters)
descriptionstringNoEvent description (max 500 characters). Use null to clear.
start_timestringNoEvent start time (flexible datetime format)
end_timestringNoEvent end time (flexible datetime format)
all_daybooleanNoWhether 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

200Event updated successfully
400Validation error or end_time <= start_time
401Invalid or missing API key
404Event not found or doesn't belong to your account
500Server error
DELETE/api/calendar/external/v1/events/{id}

Delete an event by its ID.

Authentication

Required

Path Parameters

ParameterTypeRequiredDescription
idstring (UUID)YesThe 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

200Event deleted successfully
401Invalid or missing API key
404Event not found or doesn't belong to your account
500Server error

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:00

No milliseconds/timezone (assumes UTC)

2. ISO 8601 Without Milliseconds:

2025-12-15T14:30:00Z

UTC timezone specified

3. Full ISO 8601 (RFC 3339):

2025-12-15T14:30:00.000Z
2025-12-15T14:30:00.123Z

With milliseconds and fractional seconds

4. With Timezone Offset:

2025-12-15T14:30:00+05:30
2025-12-15T14:30:00-08:00

IST and PST timezones

5. Space Separator:

2025-12-15 14:30:00

Space 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:

Input:2025-12-15T14:30:00
Stored:2025-12-15T14:30:00.000Z

Responses 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

CodeMeaningDescription
200OKRequest successful
201CreatedResource created successfully
400Bad RequestValidation error or invalid parameters
401UnauthorizedInvalid or missing API key
404Not FoundResource not found or doesn't belong to your account
500Internal Server ErrorServer 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 window
  • X-RateLimit-Reset: Unix timestamp when the rate limit resets
  • Retry-After: Number of seconds to wait before retrying (only on 429 responses)

Best Practices

  • Monitor Rate Limit Headers: Check X-RateLimit-Remaining to avoid hitting the limit
  • Implement Exponential Backoff: If you receive a 429 response, wait for the Retry-After duration 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_time to 00:00:00 and end_time to 23:59:59

3. Error Handling

  • Always check the success field in responses
  • Handle 401 errors by verifying your API key
  • Validate user input before sending requests
  • Implement retry logic for 500 errors 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_time before 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