PHPackages                             freeloapp/php-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. freeloapp/php-sdk

ActiveLibrary[HTTP &amp; Networking](/categories/http)

freeloapp/php-sdk
=================

Modern PHP SDK for Freelo API - Project and task management

v1.1.0(1mo ago)1418↓35.7%MITPHPPHP ^8.1CI passing

Since Jan 22Pushed 1mo agoCompare

[ Source](https://github.com/freeloapp/php-sdk)[ Packagist](https://packagist.org/packages/freeloapp/php-sdk)[ Docs](https://github.com/freeloapp/php-sdk)[ RSS](/packages/freeloapp-php-sdk/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (2)Dependencies (25)Versions (3)Used By (0)

Freelo PHP SDK
==============

[](#freelo-php-sdk)

[![PHP Version](https://camo.githubusercontent.com/4ff5da1bc8aecceb1679f1b36bc864f8a496c31b6b8a741a1feb93469a5fbe48/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f667265656c6f6170702f7068702d73646b2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/freeloapp/php-sdk)[![License](https://camo.githubusercontent.com/b32d0ce928f3f6193af02bb015149a1e680b3f588e9decc9747c10a130d5601a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f667265656c6f6170702f7068702d73646b2e7376673f7374796c653d666c61742d737175617265)](LICENSE)

Modern, lightweight PHP SDK for [Freelo API](https://freelo.docs.apiary.io/).

Features
--------

[](#features)

- PHP 8.1+ with strict types
- PSR-18/17/7/16 compliant (bring your own HTTP client)
- Full API coverage (projects, tasks, files, comments, time tracking, etc.)
- Dynamic credentials with server-safe per-request switching
- Low-level `call()` method for arbitrary API endpoints
- Automatic pagination support
- Rate limiting detection
- Typed exceptions for error handling

Installation
------------

[](#installation)

```
composer require freeloapp/php-sdk
```

Install an HTTP client (e.g., Guzzle):

```
composer require guzzlehttp/guzzle php-http/guzzle7-adapter nyholm/psr7
```

Quick Start
-----------

[](#quick-start)

```
use Freelo\Sdk\Freelo;
use Freelo\Sdk\Auth\ApiKeyCredentials;

$freelo = new Freelo(
    new ApiKeyCredentials('your-api-key', 'your-email@example.com'),
    userAgent: 'MyApp/1.0',
);

// List projects
foreach ($freelo->projects()->list() as $project) {
    echo $project->name . "\n";
}

// Create a task
$task = $freelo->tasks()->create(
    projectId: 123,
    tasklistId: 456,
    data: ['name' => 'New task', 'priority_enum' => 'h']
);
```

Authentication
--------------

[](#authentication)

Get your API key from [Freelo Settings](https://app.freelo.io/profil/nastaveni) (scroll to API section).

```
use Freelo\Sdk\Auth\ApiKeyCredentials;

// Using environment variables (recommended)
$credentials = new ApiKeyCredentials(
    apiKey: getenv('FREELO_API_KEY'),
    email: getenv('FREELO_EMAIL')
);

$freelo = new Freelo($credentials, userAgent: 'MyApp/1.0');
```

Usage Examples
--------------

[](#usage-examples)

### Projects

[](#projects)

```
$projects = $freelo->projects()->list();           // List active projects
$project = $freelo->projects()->get(123);          // Get project by ID
$freelo->projects()->archive(123);                 // Archive project
$freelo->projects()->activate(123);                // Activate archived project

// Paginated results
$result = $freelo->projects()->getAll(['p' => 0]);
echo "Total: " . $result->getTotal();
```

### Tasks

[](#tasks)

```
$tasks = $freelo->tasks()->listInTasklist(123, 456);  // List tasks in tasklist
$task = $freelo->tasks()->get(789);                    // Get task by ID
$freelo->tasks()->finish(789);                         // Mark as complete
$freelo->tasks()->activate(789);                       // Reopen task
$freelo->tasks()->move(789, 999);                      // Move to another tasklist
$freelo->tasks()->addComment(789, 'Comment text');     // Add comment
```

### Time Tracking

[](#time-tracking)

```
$freelo->timeTracking()->start(taskId: 123, note: 'Working');
$report = $freelo->timeTracking()->stop();

// Manual work report
$freelo->workReports()->create(123, [
    'minutes' => 120,
    'date_reported' => '2024-01-15',
    'note' => 'Development work',
]);
```

### Files

[](#files)

```
$freelo->files()->uploadToTask(taskId: 123, filePath: '/path/to/file.pdf');
$freelo->files()->download(fileId: 456, destination: '/path/to/save.pdf');
```

### Dynamic Credentials

[](#dynamic-credentials)

#### Per-request credentials (server-safe)

[](#per-request-credentials-server-safe)

Use `withCredentials()` to create an isolated instance with different credentials. Each derived instance has its own client and state — safe for concurrent requests in multi-tenant server applications.

```
// Shared base instance (e.g. in a service provider)
$freelo = new Freelo(new ApiKeyCredentials(
    apiKey: 'default-key',
    email: 'default@example.com'
));

// Per-request — fully isolated, concurrency-safe
$userFreelo = $freelo->withCredentials(new ApiKeyCredentials(
    apiKey: $user->apiKey,
    email: $user->email
));

// Optionally override userAgent per tenant
$userFreelo = $freelo->withCredentials(
    new ApiKeyCredentials($user->apiKey, $user->email),
    userAgent: 'TenantApp/1.0',
);

$projects = $userFreelo->projects()->list();
```

For simple single-user scripts, you can swap credentials in place with `setCredentials()`:

```
$freelo->setCredentials(new ApiKeyCredentials(
    apiKey: 'new-key',
    email: 'new@example.com'
));

// With userAgent override
$freelo->setCredentials(
    new ApiKeyCredentials('new-key', 'new@example.com'),
    userAgent: 'MyApp/2.0',
);
```

> **Note:** `setCredentials()` mutates the shared instance and is **not safe** for concurrent requests.

#### Lazy initialization

[](#lazy-initialization)

The SDK supports creating a client without credentials upfront. Credentials can be provided later via `setCredentials()` — validation is deferred to the first API request.

```
$freelo = new Freelo();

// ... later, when credentials are available
$freelo->setCredentials(new ApiKeyCredentials(
    apiKey: $apiKey,
    email: $email
));

$freelo->projects()->list(); // works
```

### Low-level API Calls

[](#low-level-api-calls)

Use `call()` to hit arbitrary API endpoints not yet covered by typed resource classes:

```
// GET request with query parameters
$response = $freelo->call('/projects', 'GET', params: ['p' => 0]);
$data = $response->json();

// POST request with body
$response = $freelo->call('/projects/123/tasklists/456/tasks', 'POST', data: [
    'name' => 'New task',
    'priority_enum' => 'h',
]);

// Also available on derived instances
$userFreelo = $freelo->withCredentials($credentials);
$response = $userFreelo->call('/users/me', 'GET');
```

Available Resources
-------------------

[](#available-resources)

ResourceMethodDescriptionProjects`projects()`Project managementTasks`tasks()`Task managementTasklists`tasklists()`Tasklist managementComments`comments()`Comment managementFiles`files()`File upload/downloadTask Labels`taskLabels()`Task label managementProject Labels`projectLabels()`Project label managementSubtasks`subtasks()`Subtask managementTime Tracking`timeTracking()`Time trackingWork Reports`workReports()`Work report managementUsers`users()`User managementNotifications`notifications()`NotificationsEvents`events()`Activity eventsNotes`notes()`Note managementSearch`search()`Full-text searchCustom Fields`customFields()`Custom fieldsInvoices`invoices()`Invoice managementPagination
----------

[](#pagination)

```
use Freelo\Sdk\Http\Paginator;

// Auto-paginate through all results
foreach (Paginator::fetchAll(fn($p) => $freelo->projects()->getAll(['p' => $p])) as $project) {
    echo $project->name . "\n";
}

// Manual pagination
$page = $freelo->tasks()->getAll(['p' => 0]);
echo "Page {$page->getPage()} of " . ceil($page->getTotal() / 20);
if ($page->hasNextPage()) {
    $nextPage = $freelo->tasks()->getAll(['p' => $page->getNextPage()]);
}
```

Error Handling
--------------

[](#error-handling)

```
use Freelo\Sdk\Exception\{
    ApiException,
    AuthenticationException,
    NotFoundException,
    RateLimitException,
    ValidationException
};

try {
    $project = $freelo->projects()->get(999);
} catch (NotFoundException $e) {
    // Resource not found (404)
} catch (AuthenticationException $e) {
    // Invalid credentials (401)
} catch (RateLimitException $e) {
    // Rate limited (429) - retry after $e->getRetryAfter() seconds
} catch (ValidationException $e) {
    // Invalid input (422)
} catch (ApiException $e) {
    // Other API errors
}
```

Rate Limiting
-------------

[](#rate-limiting)

The API allows 25 requests/minute. The SDK tracks limits automatically:

```
$limiter = $freelo->getClient()->getRateLimiter();
if ($limiter->isLimitExceeded()) {
    sleep($limiter->getSecondsUntilReset());
}
```

Custom HTTP Client
------------------

[](#custom-http-client)

```
use GuzzleHttp\Client;
use Http\Adapter\Guzzle7\Client as GuzzleAdapter;

$httpClient = new GuzzleAdapter(new Client(['timeout' => 30]));
$freelo = new Freelo($credentials, httpClient: $httpClient);
```

Caching (Optional)
------------------

[](#caching-optional)

```
use Symfony\Component\Cache\Psr16Cache;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;

$cache = new Psr16Cache(new FilesystemAdapter('freelo', 3600));
$freelo = new Freelo($credentials, cache: $cache);
```

Development
-----------

[](#development)

```
composer install     # Install dependencies
composer test        # Run tests
composer phpstan     # Static analysis
composer check       # Run all checks
```

Requirements
------------

[](#requirements)

- PHP 8.1+
- PSR-18 HTTP Client (e.g., Guzzle)
- PSR-17 HTTP Factories (e.g., nyholm/psr7)

License
-------

[](#license)

MIT License. See [LICENSE](LICENSE).

Links
-----

[](#links)

- [Freelo API Documentation](https://freelo.docs.apiary.io/)
- [Freelo Help - API](https://help.freelo.io/en/help/api/)

###  Health Score

42

—

FairBetter than 90% of packages

Maintenance89

Actively maintained with recent releases

Popularity20

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity44

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~55 days

Total

2

Last Release

57d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/fd9507cafa4be216dba98d1bd32ef7fe5d99c7bd28448e5c533d58ed360ddd25?d=identicon)[freeloapp](/maintainers/freeloapp)

---

Tags

apisdkhttp clientpsr-18project managementtask managementfreelofreeloapp

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/freeloapp-php-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/freeloapp-php-sdk/health.svg)](https://phpackages.com/packages/freeloapp-php-sdk)
```

###  Alternatives

[laudis/neo4j-php-client

Neo4j-PHP-Client is the most advanced PHP Client for Neo4j

184616.9k31](/packages/laudis-neo4j-php-client)[getbrevo/brevo-php

Official Brevo provided RESTFul API V3 php library

963.1M35](/packages/getbrevo-brevo-php)[phpro/http-tools

HTTP tools for developing more consistent HTTP implementations.

28137.8k](/packages/phpro-http-tools)[wordpress/php-ai-client

A provider agnostic PHP AI client SDK to communicate with any generative AI models of various capabilities using a uniform API.

26236.6k14](/packages/wordpress-php-ai-client)[claude-php/claude-php-sdk

A universal, framework-agnostic PHP SDK for the Anthropic Claude API with PSR compliance

13920.7k2](/packages/claude-php-claude-php-sdk)[mozex/anthropic-php

Anthropic PHP is a supercharged community-maintained PHP API client that allows you to interact with Anthropic API.

46365.1k13](/packages/mozex-anthropic-php)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
