API Reference
Complete documentation for the Fusion Calling APIs. Manage calendar events and leads programmatically — with copy-paste examples and a built-in request builder.
https://app.fusioncalling.comQuick Start
Get started with Fusion Calling APIs in 5 minutes.
Beginner
New to APIs? Learn the basics with step-by-step tutorials.
- Learn API fundamentals
- Make your first API call
- Understand authentication
Integrator
Connect your existing tools quickly with ready-to-use guides.
- Platform-specific guides
- Ready-to-use templates
- Quick setup instructions
Developer
Deep dive into API capabilities with the complete reference.
- Complete endpoint reference
- Interactive request builder
- Best practices
Authentication
All Fusion Calling APIs use API key authentication via the Authorization header using the Bearer token format.
Getting Your API Key
- Log in to your Fusion Calling account
- Navigate to Settings → API Keys
- Click "Generate New API Key"
- 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-hereAuthentication Examples
curl -X GET "https://app.fusioncalling.com/api/calendar/external/v1/events" \
-H "Authorization: Bearer bf207bcf-c0de-4067-bd28-45728bd305aa"Warning
Authentication Best Practices
- ✅ Store API keys in environment variables
- ✅ Rotate API keys regularly
- ✅ Use different keys for development and production
- ✅ Implement key rotation in your deployment process
- ✅ Monitor API key usage for unusual activity
- ❌ Never commit API keys to version control
- ❌ Never share API keys via email or chat
Your First Request
Make your first API call to verify your authentication and understand the response format.
1 · Test your API key
List your calendar events to confirm everything works:
curl -X GET "https://app.fusioncalling.com/api/calendar/external/v1/events" \
-H "Authorization: Bearer YOUR_API_KEY"2 · Create your first event
Create a simple event with only the required fields:
1curl -X POST "https://app.fusioncalling.com/api/calendar/external/v1/events" \
2 -H "Authorization: Bearer YOUR_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "title": "My First API Event",
6 "start_time": "2025-12-15T14:30:00",
7 "end_time": "2025-12-15T16:00:00"
8 }'Success
Calendar API
Manage calendar events programmatically with full CRUD operations, integrated video conferencing (Google Meet and Zoom), and attendees management.
- Base URL
- https://app.fusioncalling.com/api/calendar/external/v1
- Version
- v2.0
- Rate limit
- 12 requests / minute
- Auth
- Bearer API key
Endpoints at a glance
/api/calendar/external/v1/eventsList calendar events
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
from | string | Optional | Filter events from this date (inclusive). Flexible datetime formats. e.g. 2025-12-01T00:00:00 |
to | string | Optional | Filter events until this date (inclusive). Flexible datetime formats. e.g. 2025-12-31T23:59:59 |
fromOptionalFilter events from this date (inclusive). Flexible datetime formats.
2025-12-01T00:00:00toOptionalFilter events until this date (inclusive). Flexible datetime formats.
2025-12-31T23:59:59Success Response
2001{
2 "success": true,
3 "data": [
4 {
5 "id": "550e8400-e29b-41d4-a716-446655440000",
6 "title": "Team Meeting",
7 "description": "Weekly team sync",
8 "start_time": "2025-12-15T14:30:00.000Z",
9 "end_time": "2025-12-15T16:00:00.000Z",
10 "all_day": false,
11 "google_meet_enabled": true,
12 "meet_link": "https://meet.google.com/abc-defg-hij",
13 "zoom_enabled": false,
14 "zoom_meeting_id": null,
15 "zoom_join_url": null,
16 "attendees": [
17 {
18 "email": "john@example.com",
19 "display_name": "John Doe",
20 "response_status": "accepted"
21 }
22 ],
23 "caller_phone": null,
24 "caller_name": null,
25 "source": "local",
26 "created_at": "2025-12-10T10:00:00.000Z",
27 "updated_at": "2025-12-10T10:00:00.000Z"
28 }
29 ]
30}Need every status code and common errors? .
/api/calendar/external/v1/events/{id}Get a single event
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | UUID | Required | The unique identifier of the event. e.g. 550e8400-e29b-41d4-a716-446655440000 |
idRequiredThe unique identifier of the event.
550e8400-e29b-41d4-a716-446655440000Success Response
2001{
2 "success": true,
3 "data": {
4 "id": "550e8400-e29b-41d4-a716-446655440000",
5 "title": "Team Meeting",
6 "description": "Weekly team sync",
7 "start_time": "2025-12-15T14:30:00.000Z",
8 "end_time": "2025-12-15T16:00:00.000Z",
9 "all_day": false,
10 "google_meet_enabled": true,
11 "meet_link": "https://meet.google.com/abc-defg-hij",
12 "zoom_enabled": false,
13 "zoom_meeting_id": null,
14 "zoom_join_url": null,
15 "attendees": [
16 {
17 "email": "john@example.com",
18 "display_name": "John Doe",
19 "response_status": "accepted"
20 }
21 ],
22 "caller_phone": null,
23 "caller_name": null,
24 "source": "local",
25 "created_at": "2025-12-10T10:00:00.000Z",
26 "updated_at": "2025-12-10T10:00:00.000Z"
27 }
28}Need every status code and common errors? .
/api/calendar/external/v1/eventsCreate an event
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
title | string | Required | Event title (1-255 characters). e.g. Meeting with Client |
start_time | string | Required | Event start time (flexible datetime format). e.g. 2025-12-15T14:30:00 |
end_time | string | Required | Event end time (must be after start_time). e.g. 2025-12-15T16:00:00 |
description | string | Optional | Event description (max 500 characters). e.g. Discuss project requirements |
all_day | boolean | Optional | Whether the event is all-day. Must be a boolean, not a string. Video conferencing cannot be enabled for all-day events. e.g. false |
google_meet_enabled | boolean | Optional | Enable Google Meet link generation (requires Google Calendar connected). Mutually exclusive with zoom_enabled. e.g. false |
zoom_enabled | boolean | Optional | Enable Zoom meeting link generation (requires Zoom connected in Settings → Integrations). Mutually exclusive with google_meet_enabled. e.g. true |
attendees | array<object> | Optional | List of attendees (max 50). Each has email, optional display_name, and optional response_status. Duplicates are removed automatically. e.g. [{"email":"client@example.com","display_name":"Client Rep"}] |
caller_phone | string | Optional | Caller's phone number in E.164 format (e.g. +15551234567). Used for call-log link and SMS confirmation. e.g. +15551234567 |
caller_name | string | Optional | Caller's display name (max 200 characters). Used in SMS template and for display. e.g. Jane Doe |
titleRequiredEvent title (1-255 characters).
Meeting with Clientstart_timeRequiredEvent start time (flexible datetime format).
2025-12-15T14:30:00end_timeRequiredEvent end time (must be after start_time).
2025-12-15T16:00:00descriptionOptionalEvent description (max 500 characters).
Discuss project requirementsall_dayOptionalWhether the event is all-day. Must be a boolean, not a string. Video conferencing cannot be enabled for all-day events.
falsegoogle_meet_enabledOptionalEnable Google Meet link generation (requires Google Calendar connected). Mutually exclusive with zoom_enabled.
falsezoom_enabledOptionalEnable Zoom meeting link generation (requires Zoom connected in Settings → Integrations). Mutually exclusive with google_meet_enabled.
trueattendeesOptionalList of attendees (max 50). Each has email, optional display_name, and optional response_status. Duplicates are removed automatically.
[{"email":"client@example.com","display_name":"Client Rep"}]caller_phoneOptionalCaller's phone number in E.164 format (e.g. +15551234567). Used for call-log link and SMS confirmation.
+15551234567caller_nameOptionalCaller's display name (max 200 characters). Used in SMS template and for display.
Jane DoeSuccess Response
2011{
2 "success": true,
3 "data": {
4 "id": "770e8400-e29b-41d4-a716-446655440002",
5 "title": "Meeting with Client",
6 "description": "Discuss project requirements",
7 "start_time": "2025-12-15T14:30:00.000Z",
8 "end_time": "2025-12-15T16:00:00.000Z",
9 "all_day": false,
10 "google_meet_enabled": false,
11 "meet_link": null,
12 "zoom_enabled": true,
13 "zoom_meeting_id": 123456789,
14 "zoom_join_url": "https://zoom.us/j/123456789",
15 "attendees": [
16 {
17 "email": "client@example.com",
18 "display_name": "Client Rep",
19 "response_status": "needsAction"
20 }
21 ],
22 "caller_phone": "+15551234567",
23 "caller_name": "Jane Doe",
24 "source": "local",
25 "created_at": "2025-12-11T10:00:00.000Z",
26 "updated_at": "2025-12-11T10:00:00.000Z"
27 }
28}Need every status code and common errors? .
/api/calendar/external/v1/events/{id}Update an event
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | UUID | Required | The unique identifier of the event. e.g. 550e8400-e29b-41d4-a716-446655440000 |
idRequiredThe unique identifier of the event.
550e8400-e29b-41d4-a716-446655440000Request Body
| Name | Type | Required | Description |
|---|---|---|---|
title | string | Optional | Event title (1-255 characters). e.g. Updated Meeting Title |
description | string | Optional | Event description. Use null to clear. e.g. Updated description |
start_time | string | Optional | Event start time (flexible datetime format). e.g. 2025-12-15T15:00:00 |
end_time | string | Optional | Event end time (flexible datetime format). e.g. 2025-12-15T17:00:00 |
all_day | boolean | Optional | Whether the event is all-day. Must be a boolean. Video conferencing cannot be enabled for all-day events. e.g. false |
google_meet_enabled | boolean | Optional | Enable/disable Google Meet. Disabling deletes the existing Meet. Mutually exclusive with zoom_enabled. e.g. false |
zoom_enabled | boolean | Optional | Enable/disable Zoom. Disabling deletes the existing Zoom meeting. Mutually exclusive with google_meet_enabled. e.g. true |
attendees | array<object> | Optional | Replaces the entire attendees list (max 50). Duplicates are removed automatically. e.g. [{"email":"client@example.com","display_name":"Client Rep"}] |
caller_phone | string | Optional | Caller's phone number in E.164 format (e.g. +15551234567). Used for call-log link and SMS confirmation. e.g. +15551234567 |
caller_name | string | Optional | Caller's display name (max 200 characters). Used in SMS template and for display. e.g. Jane Doe |
titleOptionalEvent title (1-255 characters).
Updated Meeting TitledescriptionOptionalEvent description. Use null to clear.
Updated descriptionstart_timeOptionalEvent start time (flexible datetime format).
2025-12-15T15:00:00end_timeOptionalEvent end time (flexible datetime format).
2025-12-15T17:00:00all_dayOptionalWhether the event is all-day. Must be a boolean. Video conferencing cannot be enabled for all-day events.
falsegoogle_meet_enabledOptionalEnable/disable Google Meet. Disabling deletes the existing Meet. Mutually exclusive with zoom_enabled.
falsezoom_enabledOptionalEnable/disable Zoom. Disabling deletes the existing Zoom meeting. Mutually exclusive with google_meet_enabled.
trueattendeesOptionalReplaces the entire attendees list (max 50). Duplicates are removed automatically.
[{"email":"client@example.com","display_name":"Client Rep"}]caller_phoneOptionalCaller's phone number in E.164 format (e.g. +15551234567). Used for call-log link and SMS confirmation.
+15551234567caller_nameOptionalCaller's display name (max 200 characters). Used in SMS template and for display.
Jane DoeSuccess Response
2001{
2 "success": true,
3 "data": {
4 "id": "550e8400-e29b-41d4-a716-446655440000",
5 "title": "Updated Meeting Title",
6 "description": "Updated description",
7 "start_time": "2025-12-15T15:00:00.000Z",
8 "end_time": "2025-12-15T17:00:00.000Z",
9 "all_day": false,
10 "google_meet_enabled": false,
11 "meet_link": null,
12 "zoom_enabled": true,
13 "zoom_meeting_id": 987654321,
14 "zoom_join_url": "https://zoom.us/j/987654321",
15 "attendees": [
16 {
17 "email": "client@example.com",
18 "display_name": "Client Rep",
19 "response_status": "needsAction"
20 }
21 ],
22 "caller_phone": "+15551234567",
23 "caller_name": "Jane Doe",
24 "source": "local",
25 "created_at": "2025-12-10T10:00:00.000Z",
26 "updated_at": "2025-12-11T11:30:00.000Z"
27 }
28}Need every status code and common errors? .
/api/calendar/external/v1/events/{id}Delete an event
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | UUID | Required | The unique identifier of the event. e.g. 550e8400-e29b-41d4-a716-446655440000 |
idRequiredThe unique identifier of the event.
550e8400-e29b-41d4-a716-446655440000Success Response
200{
"success": true,
"message": "Event deleted successfully"
}Need every status code and common errors? .
Datetime Formats
The API accepts many common formats and normalizes them to ISO 8601 (UTC) for storage.
| Format | Notes |
|---|---|
"2025-12-15T14:30:00" | Simple — no timezone (assumes UTC). Recommended. |
"2025-12-15T14:30:00Z" | ISO 8601 without milliseconds, UTC. |
"2025-12-15T14:30:00.000Z" | Full ISO 8601 (RFC 3339) with milliseconds. |
"2025-12-15T14:30:00+05:30" | With timezone offset. |
"2025-12-15 14:30:00" | Space separator (assumes UTC). |
Video Conferencing
Generate meeting links automatically by enabling google_meet_enabled or zoom_enabled on create/update. Google Meet returns a meet_link; Zoom returns a zoom_meeting_id and zoom_join_url.
Warning
Enable Google Meet
{
"google_meet_enabled": true
}Requires Google Calendar connected. Returns meet_link.
Enable Zoom
{
"zoom_enabled": true
}Requires Zoom connected (Settings → Integrations). Returns zoom_join_url.
Switch providers by disabling one and enabling the other in the same PATCH:
// Google Meet -> Zoom
{
"google_meet_enabled": false,
"zoom_enabled": true
}Information
warnings array (e.g. ["zoom_not_connected"]) and the corresponding link fields stay null.Boolean Field Rules
Fields like all_day, google_meet_enabled, and zoom_enabled must be real booleans, not strings.
✓ Correct
{
"all_day": true,
"google_meet_enabled": false,
"zoom_enabled": true
}✗ Incorrect
{
"all_day": "true",
"zoom_enabled": "false"
}Warning
true, false, 1, 0) returns a validation error: "Expected boolean, received string".Attendees
Pass an attendees array (max 50) on create or update. On update the entire list is replaced. Duplicate emails are removed automatically.
1{
2 "attendees": [
3 {
4 "email": "client@example.com",
5 "display_name": "Client Rep",
6 "response_status": "needsAction"
7 },
8 {
9 "email": "team@example.com"
10 }
11 ]
12}response_status accepts one of:
needsActionaccepteddeclinedtentativeEvent Object
The full shape of a calendar event.
1{
2 "id": "uuid", // auto-generated
3 "title": "string", // 1-255 chars (required)
4 "description": "string", // optional, max 500
5 "start_time": "ISO 8601", // required
6 "end_time": "ISO 8601", // required, after start_time
7 "all_day": false, // default false
8 "google_meet_enabled": false, // default false
9 "meet_link": "string|null", // response-only (Google Meet)
10 "zoom_enabled": false, // default false
11 "zoom_meeting_id": 123456789, // response-only (Zoom)
12 "zoom_join_url": "string|null", // response-only (Zoom)
13 "attendees": [{ // optional, max 50
14 "email": "…",
15 "display_name": "string",
16 "response_status": "needsAction|accepted|declined|tentative"
17 }],
18 "caller_phone": "string|null", // optional, E.164 format
19 "caller_name": "string|null", // optional, max 200 chars
20 "source": "local|google", // response-only
21 "created_at": "ISO 8601", // response-only
22 "updated_at": "ISO 8601" // response-only
23}Leads API
Send leads from your favorite tools to Fusion Calling. v1.2 adds read (GET), PATCH updates, Default Feed routing, and atomic batch inserts.
- Base URL
- https://app.fusioncalling.com/api/leads/external/v1
- Version
- v1.2
- Rate limit
- 100 requests / minute
- Auth
- Bearer API key
Fields & Default Feed
All request bodies use JSON with these fields.
Required
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Required | Lead's full name (2-100 characters). e.g. John Doe |
phone | string | Required | 10-15 digits after normalization; +, spaces, -, () allowed. e.g. 5551234567 or +1 234 567 8900 |
nameRequiredLead's full name (2-100 characters).
John DoephoneRequired10-15 digits after normalization; +, spaces, -, () allowed.
5551234567 or +1 234 567 8900Optional
| Name | Type | Required | Description |
|---|---|---|---|
email | string | Optional | Valid email address. e.g. john@example.com |
company | string | Optional | Company name (up to 100 characters). e.g. Acme Corp |
tags | array<string> | Optional | Up to 20 tags. e.g. ["vip","website-lead"] |
campaign_id | UUID | Optional | Target campaign UUID. Omit to use the Default Feed. e.g. omit → Default Feed |
kind | enum | Optional | Optional validation; must match the target campaign kind.callsms |
emailOptionalValid email address.
john@example.comcompanyOptionalCompany name (up to 100 characters).
Acme CorptagsOptionalUp to 20 tags.
["vip","website-lead"]campaign_idOptionalTarget campaign UUID. Omit to use the Default Feed.
omit → Default FeedkindOptionalOptional validation; must match the target campaign kind.
callsmsInformation
+1 (234) 567-8900, 5551234567, and +15551234567 all match the same lead.Warning
campaign_id, leads now route to the Default Feed instead of your oldest campaign.Endpoints at a glance
/api/leads/external/v1/leadsCreate a lead
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Required | Lead's full name (2-100 characters). e.g. John Doe |
phone | string | Required | Phone number (auto-normalized to E.164). e.g. +1 234 567 8900 |
email | string | Optional | Email address. e.g. john@example.com |
company | string | Optional | Company name (up to 100 characters). e.g. Acme Corp |
tags | array<string> | Optional | Lead tags (max 20). e.g. ["vip","website-lead"] |
nameRequiredLead's full name (2-100 characters).
John DoephoneRequiredPhone number (auto-normalized to E.164).
+1 234 567 8900emailOptionalEmail address.
john@example.comcompanyOptionalCompany name (up to 100 characters).
Acme CorptagsOptionalLead tags (max 20).
["vip","website-lead"]Success Response
2011{
2 "success": true,
3 "data": {
4 "mode": "atomic",
5 "inserted": 1,
6 "leads": [
7 {
8 "id": "f1c2d3e4-5b6a-7c8d-9e0f-1a2b3c4d5e6f",
9 "name": "John Doe",
10 "phone": "+12345678900",
11 "campaign_name": "Default Feed",
12 "status": "pending",
13 "created_at": "2026-06-17T12:00:00.000Z"
14 }
15 ]
16 }
17}Need every status code and common errors? .
/api/leads/external/v1/leadsCreate leads in batch
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
leads | array<object> | Required | Array of 1-100 lead objects, each with name & phone. e.g. [{"name":"Lead 1","phone":"+1234567890"},{"name":"Lead 2","phone":"+1234567891"}] |
kind | enum | Optional | Batch-level kind. Must match the target campaign kind.callsmse.g. call |
leadsRequiredArray of 1-100 lead objects, each with name & phone.
[{"name":"Lead 1","phone":"+1234567890"},{"name":"Lead 2","phone":"+1234567891"}]kindOptionalBatch-level kind. Must match the target campaign kind.
callsmscallSuccess Response
2011{
2 "success": true,
3 "data": {
4 "mode": "atomic",
5 "inserted": 2,
6 "leads": [
7 { "id": "uuid-1", "name": "Lead 1", "phone": "+1234567890", "status": "pending" },
8 { "id": "uuid-2", "name": "Lead 2", "phone": "+1234567891", "status": "pending" }
9 ]
10 }
11}Need every status code and common errors? .
/api/leads/external/v1/leadsLookup lead by phone
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
phone | string | Required | Phone number to lookup (US 10-digit works without country code). e.g. +1234567890 |
campaign_id | UUID | Optional | Optional UUID to scope the lookup to a specific campaign. |
phoneRequiredPhone number to lookup (US 10-digit works without country code).
+1234567890campaign_idOptionalOptional UUID to scope the lookup to a specific campaign.
Success Response
2001{
2 "success": true,
3 "data": {
4 "id": "f1c2d3e4-5b6a-7c8d-9e0f-1a2b3c4d5e6f",
5 "name": "John Doe",
6 "phone": "+12345678900",
7 "email": "john@example.com",
8 "campaign_name": "Default Feed",
9 "status": "pending",
10 "created_at": "2026-06-16T12:00:00.000Z"
11 }
12}Need every status code and common errors? .
/api/leads/external/v1/leadsList leads (paginated)
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
campaign_id | UUID | Optional | Optional UUID. Omit to read from the Default Feed. |
status | enum | Optional | Filter by status.pendingin-progresscompletedfailedretrye.g. pending |
page | number | Optional | Page number (default 1). e.g. 1 |
pageSize | number | Optional | Results per page (default 50, max 100). e.g. 50 |
campaign_idOptionalOptional UUID. Omit to read from the Default Feed.
statusOptionalFilter by status.
pendingin-progresscompletedfailedretrypendingpageOptionalPage number (default 1).
1pageSizeOptionalResults per page (default 50, max 100).
50Success Response
2001{
2 "success": true,
3 "data": {
4 "campaign_name": "Default Feed",
5 "page": 1,
6 "total": 2,
7 "leads": [
8 { "id": "uuid-1", "name": "John Doe", "phone": "+12345678900", "status": "pending" },
9 { "id": "uuid-2", "name": "Jane Roe", "phone": "+12345678901", "status": "pending" }
10 ]
11 }
12}Need every status code and common errors? .
/api/leads/external/v1/leads/{lead_id}Get a lead by ID
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
lead_id | UUID | Required | Lead UUID from the POST response. e.g. f1c2d3e4-5b6a-7c8d-9e0f-1a2b3c4d5e6f |
lead_idRequiredLead UUID from the POST response.
f1c2d3e4-5b6a-7c8d-9e0f-1a2b3c4d5e6fSuccess Response
2001{
2 "success": true,
3 "data": {
4 "id": "f1c2d3e4-5b6a-7c8d-9e0f-1a2b3c4d5e6f",
5 "name": "John Doe",
6 "phone": "+12345678900",
7 "email": "john@example.com",
8 "campaign_name": "Default Feed",
9 "status": "pending"
10 }
11}Need every status code and common errors? .
/api/leads/external/v1/leadsUpdate a lead
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
phone | string | Required | Lead's phone number (identifies the lead). e.g. +1234567890 |
name | string | Optional | Updated lead name. e.g. John Doe Updated |
email | string | Optional | Updated email address. e.g. john.new@example.com |
company | string | Optional | Updated company name. e.g. New Corp |
tags | array<string> | Optional | Updated tags. e.g. vip,updated |
phoneRequiredLead's phone number (identifies the lead).
+1234567890nameOptionalUpdated lead name.
John Doe UpdatedemailOptionalUpdated email address.
john.new@example.comcompanyOptionalUpdated company name.
New CorptagsOptionalUpdated tags.
vip,updatedSuccess Response
2001{
2 "success": true,
3 "data": {
4 "id": "f1c2d3e4-5b6a-7c8d-9e0f-1a2b3c4d5e6f",
5 "name": "John Doe Updated",
6 "phone": "+12345678900",
7 "status": "pending",
8 "updated_at": "2026-06-17T12:05:00.000Z"
9 }
10}Need every status code and common errors? .
FAQ
Integration Guides
Connect Fusion Calling with your favorite tools.
GoHighLevel
Send leads from GoHighLevel to Fusion Calling whenever a contact is created.
- Go to Settings → Automation → Webhooks
- Click "Add Webhook"
- URL:
https://app.fusioncalling.com/api/leads/external/v1/leads - Method: POST
- Header:
Authorization: Bearer YOUR_API_KEY
1{
2 "name": "{{contact.name}}",
3 "phone": "{{contact.phone}}",
4 "email": "{{contact.email}}",
5 "tags": ["gohighlevel"]
6}n8n
Connect any system with visual workflows using an HTTP Request node.
- • Method: POST
- • URL:
https://app.fusioncalling.com/api/leads/external/v1/leads - • Auth: Generic Credential · header
Authorization=Bearer YOUR_API_KEY - • Body content type: JSON
Information
Zapier
Connect Fusion Calling with 5,000+ apps.
- • Facebook Lead Ads → Fusion Calling
- • Google Sheets → Fusion Calling
- • Typeform → Fusion Calling
- • HubSpot → Fusion Calling
Action: Webhooks by Zapier · POST to the Leads endpoint with the Authorization header.
Web Forms
Capture leads from website forms with server-side processing.
Warning
1<?php
2$apiKey = 'YOUR_API_KEY';
3$endpoint = 'https://app.fusioncalling.com/api/leads/external/v1/leads';
4
5$data = [
6 'name' => $_POST['name'],
7 'phone' => $_POST['phone'],
8 'email' => $_POST['email'],
9 'tags' => ['website-form'],
10];
11
12$ch = curl_init($endpoint);
13curl_setopt($ch, CURLOPT_POST, true);
14curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
15curl_setopt($ch, CURLOPT_HTTPHEADER, [
16 'Authorization: Bearer ' . $apiKey,
17 'Content-Type: application/json',
18]);
19curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
20
21$response = curl_exec($ch);
22curl_close($ch);Reference
Error codes, rate limiting, and best practices.
Error Codes
400Bad RequestCheck the request format and required fields.401UnauthorizedVerify your API key in the Authorization header.404Not FoundVerify the resource (and ID) exists.409ConflictResource already exists — use PATCH to update.429Too Many RequestsImplement retry with exponential backoff.500Server ErrorRetry with backoff; contact support if it persists.Rate Limiting
All Fusion Calling APIs implement rate limiting to protect the service from abuse and ensure fair usage across all users.
Calendar API
Limit
12 requests per minute
Window
Sliding window (last 60 seconds)
Scope
Per API key
Leads API
Limit
100 requests per minute
Window
Sliding window (last 60 seconds)
Scope
Per API key (each batch counts as 1 request)
Rate Limit Headers
All API responses include rate limit headers to help you track your usage:
| Header | Description | Example |
|---|---|---|
X-RateLimit-Limit | Maximum requests allowed | 12 |
X-RateLimit-Remaining | Requests remaining in current window | 8 |
X-RateLimit-Reset | Unix timestamp when limit resets | 1704067200 |
Retry-After | Seconds to wait before retry (429 only) | 30 |
Handling Rate Limits
When you exceed the rate limit, you'll receive a 429 Too Many Requests response with a Retry-After header indicating how many seconds to wait before retrying.
Best Practices
- ✅ Implement exponential backoff for retries
- ✅ Cache responses to reduce unnecessary requests
- ✅ Use batch operations when available
- ✅ Monitor rate limit headers in production
- ✅ Queue requests when approaching rate limits
Information
Example: Implementing Retry Logic
async function makeRequestWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
const waitTime = retryAfter ? parseInt(retryAfter) * 1000 : 5000;
// Exponential backoff
const backoffTime = waitTime * Math.pow(2, i);
await new Promise(resolve => setTimeout(resolve, backoffTime));
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}Best Practices
Security
- ✓ Store API keys in environment variables
- ✓ Use HTTPS for all requests
- ✓ Rotate keys regularly
- ✗ Never expose keys in client-side code
- ✗ Never commit keys to version control
Performance
- ✓ Use batch operations for many items
- ✓ Cache responses where appropriate
- ✓ Implement exponential backoff for 429s
- ✓ Use pagination for large datasets
Changelog
Leads API v1.2
February 2026- GET endpoints for reading leads
- PATCH endpoint for updating leads
- Default Feed campaign routing
- Atomic batch inserts (1-100)
Calendar API v1.0
December 2025- Initial release with full CRUD
- Flexible datetime formats
- Google Meet integration
- Automatic Google Calendar sync