Expert in Freshdesk helpdesk API for building integrations, extracting support data, managing tickets/contacts/companies, and automating support workflows...
Build integrations with Freshdesk's helpdesk platform using their REST API v2. Manage support tickets, contacts, companies, agents, and automate workflows. The API supports full CRUD operations on all major resources with filtering, pagination, and embedded data.
# Set environment variable
export FRESHDESK_API_KEY="your-api-key-here"
export FRESHDESK_DOMAIN="yourcompany" # From yourcompany.freshdesk.com
curl for HTTP requestsjq for JSON parsing (brew install jq on macOS)https://{domain}.freshdesk.com/api/v2/
Replace {domain} with your Freshdesk subdomain (e.g., acme for acme.freshdesk.com).
Freshdesk uses HTTP Basic Authentication with your API key as the username and X as the password.
# Using -u flag (username:password)
curl -u "$FRESHDESK_API_KEY:X" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/tickets"
# Using Authorization header
curl -H "Authorization: Basic $(echo -n "$FRESHDESK_API_KEY:X" | base64)" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/tickets"
Always include:
Content-Type: application/json
curl -u "$FRESHDESK_API_KEY:X" \
-H "Content-Type: application/json" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/tickets"
curl -u "$FRESHDESK_API_KEY:X" \
-H "Content-Type: application/json" \
-X POST \
-d '{
"subject": "Support needed",
"description": "Details of the issue...",
"email": "customer@example.com",
"priority": 2,
"status": 2
}' \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/tickets"
curl -u "$FRESHDESK_API_KEY:X" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/contacts/12345"
# Search by status and priority
curl -u "$FRESHDESK_API_KEY:X" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/search/tickets?query=\"status:2 AND priority:3\""
| Endpoint | Description |
|---|---|
/tickets |
Create, list, update, delete tickets |
/contacts |
Manage customer contacts |
/companies |
Manage company/organization records |
/agents |
View and manage support agents |
/groups |
Manage agent groups |
/conversations |
Ticket replies, notes, forwards |
/time_entries |
Time tracking on tickets |
/surveys/satisfaction_ratings |
Customer satisfaction data |
/products |
Product catalog management |
/business_hours |
Business hours configuration |
/email_configs |
Email settings |
/sla_policies |
SLA policy management |
/canned_responses |
Pre-defined response templates |
/ticket_fields |
Custom ticket fields |
See references/tickets-api.md for detailed ticket operations. See references/contacts-companies.md for contact/company management.
| Version | Limit |
|---|---|
| API v1 | 1000 calls/hour |
| API v2 | Per-minute, plan-based |
| Trial Plans | 50 calls/minute |
Every response includes:
| Header | Description |
|---|---|
X-Ratelimit-Total |
Total calls allowed per minute |
X-Ratelimit-Remaining |
Calls remaining this minute |
X-Ratelimit-Used-CurrentRequest |
Credits used by this request |
#!/usr/bin/env bash
# Retry with exponential backoff for 429 errors
max_retries=3
retry_count=0
while [ "$retry_count" -lt "$max_retries" ]; do
response=$(curl -s -w "\n%{http_code}" -u "$FRESHDESK_API_KEY:X" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/tickets")
http_code=$(echo "$response" | tail -1)
body=$(echo "$response" | sed '$d')
if [ "$http_code" = "200" ]; then
echo "$body"
exit 0
elif [ "$http_code" = "429" ]; then
delay=$((2 ** retry_count))
echo "Rate limited. Retrying in ${delay}s..." >&2
sleep "$delay"
retry_count=$((retry_count + 1))
else
echo "Error: HTTP $http_code" >&2
echo "$body" >&2
exit 1
fi
done
echo "Max retries exceeded" >&2
exit 1
Some operations consume multiple API credits:
include= parameter): +1 credit per include?include=requester,company costs 3 credits total| Parameter | Default | Max | Description |
|---|---|---|---|
page |
1 | - | Page number (1-indexed) |
per_page |
30 | 100 | Results per page |
page=1
while true; do
response=$(curl -s -u "$FRESHDESK_API_KEY:X" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/tickets?page=$page&per_page=100")
count=$(echo "$response" | jq length)
if [ "$count" -eq 0 ]; then
break
fi
echo "$response" | jq '.[] | {id, subject, status}'
page=$((page + 1))
done
Responses include a Link header for navigation:
Link: <https://domain.freshdesk.com/api/v2/tickets?page=2>; rel="next"
Common filters available on list endpoints:
| Parameter | Example | Description |
|---|---|---|
filter |
new_and_my_open |
Pre-defined filter |
requester_id |
12345 |
Filter by requester |
company_id |
67890 |
Filter by company |
updated_since |
2024-01-01T00:00:00Z |
Modified after date |
# New and open tickets assigned to me
curl -u "$FRESHDESK_API_KEY:X" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/tickets?filter=new_and_my_open"
# All unresolved tickets
curl -u "$FRESHDESK_API_KEY:X" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/tickets?filter=all_unresolved"
# Tickets updated in last 30 days
curl -u "$FRESHDESK_API_KEY:X" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/tickets?updated_since=2024-11-01T00:00:00Z"
Embed related objects to reduce API calls:
# Include requester and company with ticket
curl -u "$FRESHDESK_API_KEY:X" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/tickets/123?include=requester,company"
# Include stats with ticket list
curl -u "$FRESHDESK_API_KEY:X" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/tickets?include=stats"
Available includes for tickets: requester, company, stats, conversations, description
The Search API enables complex queries across tickets, contacts, and companies.
curl -u "$FRESHDESK_API_KEY:X" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/search/tickets?query=\"<query>\""
# Tickets with specific status and priority
"status:2 AND priority:3"
# Tickets from a specific requester
"requester_email:'customer@example.com'"
# Tickets created in date range
"created_at:>'2024-01-01' AND created_at:<'2024-02-01'"
# Tickets with specific tag
"tag:'urgent'"
# Tickets assigned to specific agent
"agent_id:12345"
# Full-text search in subject and description
"~'password reset'"
| Operator | Description |
|---|---|
AND |
Both conditions must match |
OR |
Either condition matches |
: |
Equals |
:> |
Greater than |
:< |
Less than |
~ |
Full-text search |
| Value | Status |
|---|---|
| 2 | Open |
| 3 | Pending |
| 4 | Resolved |
| 5 | Closed |
| Value | Priority |
|---|---|
| 1 | Low |
| 2 | Medium |
| 3 | High |
| 4 | Urgent |
| Value | Source |
|---|---|
| 1 | |
| 2 | Portal |
| 3 | Phone |
| 7 | Chat |
| 8 | Mobihelp |
| 9 | Feedback Widget |
| 10 | Outbound Email |
| Code | Meaning | Action |
|---|---|---|
| 200 | Success | Process response |
| 201 | Created | Resource created successfully |
| 204 | No Content | Delete successful |
| 400 | Bad Request | Check request body/params |
| 401 | Unauthorized | Verify API key |
| 403 | Forbidden | Check permissions |
| 404 | Not Found | Verify resource ID |
| 409 | Conflict | Resource already exists |
| 429 | Rate Limited | Wait and retry |
| 500 | Server Error | Retry with backoff |
{
"description": "Validation failed",
"errors": [
{
"field": "email",
"message": "It should be a valid email address.",
"code": "invalid_value"
}
]
}
Freshdesk can send webhook notifications on ticket events. Configure webhooks in Admin โ Automations โ Webhooks.
{
"freshdesk_webhook": {
"ticket_id": 12345,
"ticket_subject": "Support needed",
"ticket_status": "Open",
"ticket_priority": "Medium",
"ticket_requester_email": "customer@example.com",
"triggered_event": "ticket_created"
}
}
See references/webhooks-automation.md for detailed webhook setup.
include parameter - Reduce API calls by embedding dataper_page=100 for bulk operationsYYYY-MM-DDTHH:MM:SSZ| Language | Package | Install |
|---|---|---|
| Python | python-freshdesk |
pip install python-freshdesk |
| Node.js | node-freshdesk-api |
npm install node-freshdesk-api |
| Ruby | freshdesk-ruby |
gem install freshdesk |
| PHP | Official samples | See Freshdesk docs |
| Java | Official samples | See Freshdesk docs |
See references/sdk-examples.md for detailed code examples.
#!/usr/bin/env bash
# Export all tickets to tickets.json
page=1
echo "[" > tickets.json
first=true
while true; do
response=$(curl -s -u "$FRESHDESK_API_KEY:X" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/tickets?page=$page&per_page=100&include=description")
count=$(echo "$response" | jq length)
[ "$count" -eq 0 ] && break
if [ "$first" = true ]; then
first=false
else
echo "," >> tickets.json
fi
echo "$response" | jq '.[]' | paste -sd ',' - >> tickets.json
page=$((page + 1))
sleep 0.5 # Respect rate limits
done
echo "]" >> tickets.json
echo "Exported $((page - 1)) pages of tickets"
#!/usr/bin/env bash
# Import contacts from contacts.csv (name,email,company_id)
while IFS=, read -r name email company_id; do
curl -s -u "$FRESHDESK_API_KEY:X" \
-H "Content-Type: application/json" \
-X POST \
-d "{\"name\":\"$name\",\"email\":\"$email\",\"company_id\":$company_id}" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/contacts"
sleep 0.5
done < contacts.csv
# Get resolution time stats for closed tickets this month
curl -s -u "$FRESHDESK_API_KEY:X" \
"https://$FRESHDESK_DOMAIN.freshdesk.com/api/v2/search/tickets?query=\"status:5 AND created_at:>'2024-12-01'\"" \
| jq '[.results[] | .stats.resolved_at as $r | .created_at as $c |
(($r | fromdateiso8601) - ($c | fromdateiso8601)) / 3600] |
{count: length, avg_hours: (add / length)}'
For detailed endpoint documentation: