PHPackages                             laragear/api-manager - 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. laragear/api-manager

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

laragear/api-manager
====================

Manage multiple REST servers to make requests in few lines and fluently.

v4.0.0(2mo ago)161.8k—0%1MITPHPPHP ^8.3CI passing

Since Feb 22Pushed 2mo ago2 watchersCompare

[ Source](https://github.com/Laragear/ApiManager)[ Packagist](https://packagist.org/packages/laragear/api-manager)[ Fund](https://github.com/sponsors/DarkGhostHunter)[ Fund](https://paypal.me/darkghosthunter)[ RSS](/packages/laragear-api-manager/feed)WikiDiscussions 4.x Synced 1mo ago

READMEChangelog (5)Dependencies (6)Versions (9)Used By (0)

Api Manager
===========

[](#api-manager)

[![Latest Version on Packagist](https://camo.githubusercontent.com/fcf21ff7ba05140a55bb3f281836860e37991362f1606ac3308e92d6f46c4b73/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6c617261676561722f6170692d6d616e616765722e737667)](https://packagist.org/packages/laragear/api-manager)[![Latest stable test run](https://github.com/Laragear/ApiManager/workflows/Tests/badge.svg)](https://github.com/Laragear/ApiManager/actions)[![Codecov Coverage](https://camo.githubusercontent.com/a7e92a42b9fa5ffb84be1c7477941a2fb68c2bbc17fcd8b5402f89e4ee0e0743/68747470733a2f2f636f6465636f762e696f2f67682f4c617261676561722f4170694d616e616765722f67726170682f62616467652e7376673f746f6b656e3d56373236756430737336)](https://codecov.io/gh/Laragear/ApiManager)[![Maintainability](https://camo.githubusercontent.com/2daf78aa7b20432acf16aef0ebc76e57fe1529cfc916d72cf4e012781e72f6b8/68747470733a2f2f716c74792e73682f6261646765732f66326466333834632d343433392d343731352d393438662d3937643934393636636662372f6d61696e7461696e6162696c6974792e737667)](https://qlty.sh/gh/Laragear/projects/ApiManager)[![Sonarcloud Status](https://camo.githubusercontent.com/faa62db15cd8124edae1f917c5e34c172ad9ff74dd6325f970c732af4fb6f87f/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d4c617261676561725f4170694d616e61676572266d65747269633d616c6572745f737461747573)](https://sonarcloud.io/dashboard?id=Laragear_ApiManager)[![Laravel Octane Compatibility](https://camo.githubusercontent.com/70359a356da237cd29561bc5d0bb80baae775b5ff62f288ed324755382858342/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2532304f6374616e652d436f6d70617469626c652d737563636573733f7374796c653d666c6174266c6f676f3d6c61726176656c)](https://laravel.com/docs/11.x/octane#introduction)

Manage multiple REST servers to make requests in few lines and fluently. No more verbose HTTP Requests!

```
use App\Http\Apis\Chirper;

$chirp = Chirper::api()->chirp('Hello world!');
```

Become a sponsor
----------------

[](#become-a-sponsor)

[![](.github/assets/support.png)](https://github.com/sponsors/DarkGhostHunter)

Your support allows me to keep this package free, up-to-date and maintainable. Alternatively, you can **[spread the word!](http://twitter.com/share?text=I%20am%20using%20this%20cool%20PHP%20package&url=https://github.com%2FLaragear%2FPreload&hashtags=PHP,Laravel)**

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

[](#requirements)

- PHP 8.3 or later
- Laravel 12 or later

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

[](#installation)

Require this using Composer into your project:

```
composer require laragear/api-manager
```

Usage
-----

[](#usage)

### Creating an API Server

[](#creating-an-api-server)

To make use of an API server, define a class that extends `Laragear\ApiManager\ApiServer`. You may use the `make:api` Artisan command to make a ready-made stub in the `app\Http\Apis` directory.

```
php artisan make:api Chirper
```

You will receive a file with a base URL and actions, and space to add some headers and a bearer token. You're free to adjust it to your needs.

```
namespace App\Http\Apis;

use Laragear\ApiManager\ApiServer;
use Laragear\ApiManager\Attributes\Action;

#[Action('latest', '/')]
#[Action('create', 'post', 'new')]
class Chirper extends ApiServer
{
    /**
     * The headers to include in each request.
     *
     * @var array{string:string}|array
     */
    public array $headers = [
        // ...
    ];

    /**
     * Returns the API base URL.
     */
    public function getBaseUrl(): string
    {
        return app()->isProduction()
            ? 'https://chirper.com/api/v1'
            : 'https://dev.chirper.com/api/v1';
    }

     /**
      * Returns the Bearer Token used for authentication.
      */
     protected function authToken(): string
     {
         return config('services.chirper.secret');
     }
}
```

Note

You can override the API Server stub creating one in `stubs/api.stub`.

### Inline Actions

[](#inline-actions)

Setting actions in the API class solves the problem of having multiple endpoints and preparing each one every time across your application, which can led to errors or convoluted functions full of text.

The easiest way to define actions is to use the `Laragear\ApiManager\Attributes\Action` attribute on top of the class with the action name in camelCase (like it was a class method), and the URL path. You may also set the HTTP verb to use, otherwise `get` will be inferred.

```
namespace App\Http\Apis;

use Laragear\ApiManager\ApiServer;
use Laragear\ApiManager\Attributes\Action;

#[Action('newChirp', 'post', 'new')]
#[Action('latest', 'latest')]
#[Action('view', 'chirp/{id}')]
#[Action('edit', 'update', 'chirp/{id}')]
#[Action('delete', 'delete', 'chirp/{id}')]
class Chirper extends ApiServer
{
    // ...
}
```

For example, to see the latest chirp on the server, we could call `latest` directly from our `ChirpApi`.

```
use App\Http\Apis\Chirper;

$latestChirps = Chirper::api()->latest();
```

Alternatively, you can call an action without arguments as it were a property, especially if just a `GET` method over the server.

```
use App\Http\Apis\Chirper;

$latestChirps = Chirper::api()->latest;
```

When calling an action that requires parameters, the arguments will be passed down to the HTTP Request as part of the body.

```
use App\Http\Apis\Chirper;

// Create a new chirp.
$chirp = Chirper::api()->newChirp(['message' => 'This should be complex']);
```

If the route has named parameters, lile `chirp/{id}`, you can set them as arguments when invoking the server.

```
use App\Http\Apis\Chirper;

// Edit a chirp.
Chirper::api(['id' => 231])->edit(['message' => 'No, it was a breeze!']);

// Same as:
Chirper::api('chirper')->withUrlParameters(['id' => 231])->edit(['message' => 'No, it was a breeze!']);
```

While you're at it, add the PHPDoc manually to your API Server to take advantage of autocompletion in your IDE (intellisense).

```
use Laragear\ApiManager\ApiServer;
use Laragear\ApiManager\Attributes\Action;

/**
 * @method \Illuminate\Http\Client\Response newChirp($data = [])
 * @property-read \Illuminate\Http\Client\Response $latest
 * @property-read  \Illuminate\Http\Client\Response $view
 * @method \Illuminate\Http\Client\Response edit($data = [])
 * @method \Illuminate\Http\Client\Response delete()
 */

#[Action('newChirp', 'post', 'new')]
#[Action('latest', 'latest')]
#[Action('view', 'chirp/{id}')]
#[Action('edit', 'update', 'chirp/{id}')]
#[Action('delete', 'delete', 'chirp/{id}')]
class Chirper extends ApiServer
{
    // ...
}
```

Note

You can still use the old way of using the `$actions` array, but is being deprecated.

### Method actions

[](#method-actions)

For more complex scenarios, you may use a class method. Just be sure to type-hint the `PendingRequest` on any parameter if you need to customize the request.

```
use Illuminate\Http\Client\PendingRequest;

public function newChirp(PendingRequest $request, string $message)
{
    return $request->connectTimeout(10)->post('new', ['message' => $message]);
}

public function noReply(PendingRequest $request)
{
    $request->withHeaders(['X-No-Reply' => 'false'])

    return $this;
}
```

Then later, you can invoke the class methods like any Monday morning.

```
use App\Http\Apis\Chirper;

$chirp = Chirper::api()->newChirp('Easy peasy');
```

Note

Method actions take precedence over inline actions.

As with inline actions, method actions can be also executed as it where properties if these don't require arguments.

```
use App\Http\Apis\Chirper;

$latest = Chirper::api()->noReply->newChirp('Easy peasy');
```

### Authentication

[](#authentication)

An API Server supports the [three kinds authentication of the HTTP Client in Laravel](https://laravel.com/docs/11.x/http-client#authentication): Basic, Digest and Bearer Token. You may define each of them as an array of username and password using `authBasic()` or `authDigest()`, and `authToken()` with the token, respectively.

```
/**
 * Returns the Basic Authentication to use against the API.
 *
 * @var array{string, string}|array|void
 */
public function authBasic(): array
{
    return app()->isProduction()
        ? ['app@chirper.com' => 'real-password']
        : ['dev@chirper.com' => 'fake-password'];
}
```

Warning

Don't use an associative array to match the underlying methods. Since [Laravel doesn't warranty consistency on named arguments](https://laravel.com/docs/11.x/releases#named-arguments), you should opt for simple arrays or `key => value`.

```
// This is still supported, but discouraged!
return ['username' => 'app@chirper', 'password' => 'real-password'];
```

### Before &amp; After building a request

[](#before--after-building-a-request)

You can modify the request before and after it's bootstrapped using the `beforeBuild()` and `afterBuild()` respectively. The `beforeBuild()` is executed after the `PendingRequest` instance receives the base URL, and the `afterBuild()` is called after the headers and authentication are incorporated.

```
use Illuminate\Http\Client\PendingRequest;

public function beforeBuild(PendingRequest $request)
{
    //
}

public function afterBuild(PendingRequest $request)
{
    //
}
```

You're free here to tap into the request instance and modify it for all endpoints, or return an entirely new `PendingRequest` instance.

### Overriding a request

[](#overriding-a-request)

The API request can be overridden as usual. All methods are passed down to the `Illuminate\Http\Client\PendingRequest` instance if these don't exist on the API Class.

```
use App\Http\Apis\Chirper;

$chirp = Chirper::api()->timeout(5)->latest();
```

Note

If the method exists in your API Class, it will take precedence.

### Dependency Injection

[](#dependency-injection)

All API Servers are resolved using the Service Container, so you can add any service you need to inject in your object through the constructor.

```
use Illuminate\Filesystem\Filesystem;
use Laragear\ApiManager\ApiServer;

class Chirper extends ApiServer
{
    public function __construct(protected Filesystem $file)
    {
        if ($this->file->missing('important_file.txt')) {
            throw new RuntimeException('Important file missing!')
        }
    }

    // ...
}
```

You can also create a callback to resolve your API Server in your `AppServiceProvider` if you need more deep customization to create it.

```
// app\Providers\AppServiceProvider.php
use App\Http\Apis\Chirper;

public function register()
{
    $this->app->bind(Chirper::class, function () {
       return new Chirper(config('services.chirper.version'));
    })
}
```

### Concurrent Requests

[](#concurrent-requests)

To add an API Server Request to a pool, use the `onPool()` method for each concurrent request. There is no need to make all requests to the same API server, as you can mix and match different destinations.

```
use Illuminate\Support\Facades\Http;
use App\Http\Apis\Chirper;
use App\Http\Apis\Twitter;

$responses = Http::pool(fn ($pool) => [
    Chirper::api()->on($pool)->chirp('Hello world!'),
    Twitter::api()->on($pool)->tweet('Goodbye world!'),
    $pool->post('mastodon.org/api', ['message' => 'Greetings citizens!'])
]);

return $responses[0]->ok();
```

You may also name the requests using a second argument to `on()`.

```
use Illuminate\Support\Facades\Http;
use App\Http\Apis\Chirper;
use App\Http\Apis\Twitter;

$responses = Http::pool(fn ($pool) => [
    Chirper::api()->on($pool, 'first')->chirp('Hello world!'),
    Twitter::api()->on($pool, 'second')->tweet('Goodbye world!'),
    $pool->as('third')->post('mastodon.org/api', ['message' => 'Greetings citizens!'])
]);

return $responses['first']->ok();
```

### Wrapping into custom responses

[](#wrapping-into-custom-responses)

You may find yourself receiving a response and having to map the data to your own class manually for convenience. Instead of juggling your way to do that, you can automatically wrap the incoming response into a custom "API Response."

First, create a custom response for an api using `make:api-response`, the API you want to use, and name the custom response with the same name of the endpoint. Ideally, you would want to name it the same as the action or method you plan to use it for.

```
php artisan make:api-response Chirper ViewResponse
```

You will receive a file in `App\Http\Apis\{ApiServer}\Responses` like this:

```
namespace App\Http\Apis\Chirper\Responses;

use Illuminate\Http\Client\Response;

class ViewResponse extends Response
{
    //
}
```

Note

You can override the API Response stub creating one in `stubs/api-response.stub`.

In this class you can make any method you want. Since your class will extend the base [Laravel HTTP Client](https://laravel.com/docs/11.x/http-client) `Response` class, you will have access to all its convenient methods.

```
class ViewResponse extends Response
{
    /**
     * Determine if the chirp is private.
     */
    public function isPrivate(): bool
    {
        return $this->json('metadata.is_private', false)
    }
}
```

Once you finish up customizing your custom API Response, you may set the `Laragear\ApiManager\Attributes\Response` attribute with the response class name on top of your method.

```
use Laragear\ApiManager\Attributes\Response;

#[Response(Responses\ViewResponse::class)]
public function view()
{
    //...
}
```

Note

You can still use the old `$responses` array to map custom Responses to your method, but is being deprecated.

This will enable the API Manager to wrap the response into your own every time you call that method to receive a response. For example, if you call `view()`, you will receive a new `ViewResponse` instance.

```
use App\Http\Apis\Chirper;

$chirp = Chirper::api(['id' => 5])->view();

if ($chirp->successful() && $chirp->isPrivate()) {
    return 'The chirp cannot be seen publicly.';
}
```

Tip

When using `async()` requests, custom responses are automatically wrapped once resolved.

Testing
-------

[](#testing)

You can test if an API Server action works or not by using [the `fake()` method of the HTTP facade](https://laravel.com/docs/11.x/http-client#testing).

```
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\Request;

public function test_creates_new_chirp(): void
{
    Http::fake(function (Request $request) {
        return Http::response([
            'posted' => 'ok',
            ...json_decode($request->body())
        ], 200);
    });

    $this->post('spread-message', ['message' => 'Hello world!'])
        ->assertSee('Posted!');
}
```

Laravel Octane Compatibility
----------------------------

[](#laravel-octane-compatibility)

- There are no singletons using a stale application instance.
- There are no singletons using a stale config instance.
- There are no singletons using a stale request instance.
- There are no static properties written.

There should be no problems using this package with Laravel Octane.

Security
--------

[](#security)

If you discover any security-related issues, please [use the online form](https://github.com/Laragear/ApiManager/security).

License
=======

[](#license)

This specific package version is licensed under the terms of the [MIT License](LICENSE.md), at the time of publishing.

[Laravel](https://laravel.com) is a Trademark of [Taylor Otwell](https://github.com/TaylorOtwell/). Copyright © 2011–2026 Laravel LLC.

###  Health Score

51

—

FairBetter than 96% of packages

Maintenance87

Actively maintained with recent releases

Popularity27

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

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 ~138 days

Recently: every ~100 days

Total

9

Last Release

65d ago

Major Versions

1.x-dev → v2.0.02024-03-14

v2.0.1 → 3.x-dev2025-03-29

v3.0.0 → 4.x-dev2026-03-05

PHP version history (4 changes)v1.0.0PHP 8.\*

v2.0.0PHP ^8.1

3.x-devPHP ^8.2

4.x-devPHP ^8.3

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/5141911?v=4)[Italo](/maintainers/DarkGhostHunter)[@DarkGhostHunter](https://github.com/DarkGhostHunter)

---

Top Contributors

[![DarkGhostHunter](https://avatars.githubusercontent.com/u/5141911?v=4)](https://github.com/DarkGhostHunter "DarkGhostHunter (14 commits)")

---

Tags

httpapiclientlaravelrest

### Embed Badge

![Health badge](/badges/laragear-api-manager/health.svg)

```
[![Health](https://phpackages.com/badges/laragear-api-manager/health.svg)](https://phpackages.com/packages/laragear-api-manager)
```

###  Alternatives

[api-platform/laravel

API Platform support for Laravel

59126.4k6](/packages/api-platform-laravel)[omniphx/forrest

A Laravel library for Salesforce

2724.4M8](/packages/omniphx-forrest)[cybercog/youtrack-rest-php

YouTrack REST API PHP Client.

37149.2k3](/packages/cybercog-youtrack-rest-php)[vinelab/http

An http library developed for the laravel framework. aliases itself as HttpClient

59300.2k11](/packages/vinelab-http)[rap2hpoutre/jacky

Opinionated REST JSON HTTP API client for laravel

174.4k](/packages/rap2hpoutre-jacky)[meteocontrol/vcom-api-client

HTTP Client for meteocontrol's VCOM API - The VCOM API enables you to directly access your data on the meteocontrol platform.

175.7k1](/packages/meteocontrol-vcom-api-client)

PHPackages © 2026

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