mohamed-fathy/freshdesk-php-sdk
PHP 5.5+ SDK for Freshdesk API v2. Create an Api client with your API key and domain, then manage tickets, contacts, agents, companies, groups, and more with simple CRUD methods returning plain arrays.
Installation:
composer require mpclarkson/freshdesk-php-sdk
Basic Initialization (in a Laravel service provider or controller):
use Freshdesk\Api;
$api = new Api(config('services.freshdesk.api_key'), config('services.freshdesk.domain'));
Add to config/services.php:
'freshdesk' => [
'api_key' => env('FRESHDESK_API_KEY'),
'domain' => env('FRESHDESK_DOMAIN'),
],
First Use Case: Fetch all tickets with pagination:
$tickets = $api->tickets->all(['page' => 1, 'per_page' => 20]);
Service Provider:
Register the SDK as a singleton in AppServiceProvider:
public function register()
{
$this->app->singleton('freshdesk', function ($app) {
return new Api(config('services.freshdesk.api_key'), config('services.freshdesk.domain'));
});
}
Facade (Optional):
Create a facade (app/Facades/Freshdesk.php) for cleaner syntax:
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Freshdesk extends Facade
{
protected static function getFacadeAccessor() { return 'freshdesk'; }
}
Usage:
Freshdesk::tickets()->all();
Request Scoping: Use middleware to inject the API instance into requests:
public function handle($request, Closure $next)
{
$request->merge(['freshdesk' => app('freshdesk')]);
return $next($request);
}
Ticket Management:
// Create a ticket
$ticket = $api->tickets->create([
'subject' => 'Laravel Issue',
'description' => 'Need help with...',
'requester_id' => 123,
]);
// Update a ticket
$api->tickets->update($ticket['id'], ['status' => 2]);
// Fetch tickets with filters
$openTickets = $api->tickets->all(['status' => 2]);
Contact Sync:
// Create a contact
$contact = $api->contacts->create([
'name' => 'John Doe',
'email' => 'john@example.com',
]);
// Convert contact to agent
$api->contacts->makeAgent($contact['id']);
Automated Responses:
// Add a note to a ticket
$api->conversations->note($ticketId, [
'body' => 'Automated response: ...',
]);
Data Migration:
// Fetch all companies
$companies = $api->companies->all();
// Sync with local DB
foreach ($companies as $company) {
Company::updateOrCreate(
['freshdesk_id' => $company['id']],
$company
);
}
Wrap API calls in a try-catch block:
try {
$result = $api->tickets->view($id);
} catch (\Freshdesk\Exceptions\ApiException $e) {
\Log::error('Freshdesk API Error: ' . $e->getMessage());
return response()->json(['error' => 'Failed to fetch ticket'], 500);
}
API Credits:
include=company) consumes extra credits. Monitor usage via Freshdesk’s API dashboard.include=requester,company costs 3 credits (1 for ticket + 2 for includes).Rate Limiting:
$tickets = Cache::remember("freshdesk_tickets_{$page}", now()->addHours(1), function () use ($api, $page) {
return $api->tickets->all(['page' => $page]);
});
Data Validation:
if (!isset($ticket['id']) || empty($ticket['subject'])) {
throw new \InvalidArgumentException('Invalid ticket data');
}
Missing Features:
$client = $api->getClient();
$response = $client->get("https://{$api->getDomain()}/api/v2/solutions");
Deprecated Methods:
dev-master branch is outdated (last release: 2020). Fork and extend if critical features are missing.Enable Guzzle Debugging: Configure the SDK to log requests/responses:
$api = new Api($key, $domain);
$api->getClient()->getEmitter()->attach(
new \GuzzleHttp\Middleware::tap(function ($request, $options) {
\Log::debug('Freshdesk Request:', [
'url' => (string) $request->getUri(),
'method' => $request->getMethod(),
'body' => $request->getBody(),
]);
})
);
Common HTTP Errors:
api_key and domain.ticket_id must exist).Custom Resources:
Extend AbstractResource to add unsupported endpoints (e.g., Solutions):
namespace App\Freshdesk;
use Freshdesk\Resources\AbstractResource;
class Solution extends AbstractResource
{
protected $resource = 'solutions';
public function all(array $query = null) { return $this->get($query); }
}
Request/Response Transformers:
Override the SDK’s transformResponse method to normalize data:
$api->setTransformer(function ($response) {
return collect($response)->map(function ($item) {
return [
'id' => $item['id'] ?? null,
'name' => $item['name'] ?? '',
// ...
];
})->toArray();
});
Webhook Integration:
Use Laravel’s queue:work to process Freshdesk webhooks asynchronously:
// In your webhook route
dispatch(new ProcessFreshdeskWebhook($payload));
Batch Processing:
Use per_page=100 (max allowed) to reduce API calls:
$tickets = $api->tickets->all(['per_page' => 100]);
Lazy Loading: Implement iterators for large datasets:
class TicketIterator implements \Iterator
{
private $api;
private $page = 1;
private $current;
public function __construct($api) { $this->api = $api; }
public function current() { return $this->current; }
public function next() {
$this->page++;
$this->current = $this->api->tickets->all(['page' => $this->page])[0] ?? null;
}
// ... (implement key/valid)
}
Caching Strategies: Cache filtered results with unique keys:
Cache::remember("freshdesk_tickets_status_{$status}", now()->addMinutes(5), function () use ($api, $status) {
return $api->tickets->all(['status' => $status]);
});
Domain Format:
Ensure the domain is correct (e.g., yourdomain.freshdesk.com, not https://...).
$api = new Api($key, 'yourdomain'); // No protocol or trailing slash
Environment Variables:
Store sensitive keys in .env:
FRESHDESK_API_KEY=your_api_key_here
FRESHDESK_DOMAIN=yourdomain
Timeouts: Adjust Guzzle’s timeout in the SDK’s client:
$api->setClientConfig(['timeout' => 30]); // 30 seconds
How can I help you explore Laravel packages today?