PHPackages                             xbnz/google-gemini-api - 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. [API Development](/categories/api)
4. /
5. xbnz/google-gemini-api

ActiveLibrary[API Development](/categories/api)

xbnz/google-gemini-api
======================

HTTP clients for accessing Google's AI models and OAuth2 service

2.0.0(1y ago)617MITPHPPHP ^8.4CI passing

Since May 21Pushed 1y ago1 watchersCompare

[ Source](https://github.com/XbNz/gemini)[ Packagist](https://packagist.org/packages/xbnz/google-gemini-api)[ RSS](/packages/xbnz-google-gemini-api/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (5)Dependencies (17)Versions (7)Used By (0)

[![Test suite](https://camo.githubusercontent.com/083d608b13b2f0ff6257c15f4a86858868c763a9464c6119dc0d2f9142b42a02/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f58624e7a2f67656d696e692f72756e2d74657374732e796d6c3f6c6162656c3d5465737473266c6f676f3d676974687562267374796c653d666c61742d737175617265)](https://camo.githubusercontent.com/083d608b13b2f0ff6257c15f4a86858868c763a9464c6119dc0d2f9142b42a02/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f58624e7a2f67656d696e692f72756e2d74657374732e796d6c3f6c6162656c3d5465737473266c6f676f3d676974687562267374796c653d666c61742d737175617265)[![Test suite](https://camo.githubusercontent.com/c6f7970612fa14294d96cf08509157977ea26589e7cea462d88124d1da3ae78d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f58624e7a2f67656d696e692f7068707374616e2e796d6c3f6c6162656c3d5048505374616e266c6f676f3d676974687562267374796c653d666c61742d737175617265)](https://camo.githubusercontent.com/c6f7970612fa14294d96cf08509157977ea26589e7cea462d88124d1da3ae78d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f58624e7a2f67656d696e692f7068707374616e2e796d6c3f6c6162656c3d5048505374616e266c6f676f3d676974687562267374796c653d666c61742d737175617265)[![Release](https://camo.githubusercontent.com/52905db319b25ac34fe8fb6618c3e331732111f3437ede38366baa80787d2460/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f58624e7a2f67656d696e693f7374796c653d666c61742d737175617265)](https://camo.githubusercontent.com/52905db319b25ac34fe8fb6618c3e331732111f3437ede38366baa80787d2460/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f58624e7a2f67656d696e693f7374796c653d666c61742d737175617265)[![License](https://camo.githubusercontent.com/59724e6687b9ec6a9b6f514ce16c123a4234146373c3e98b71e90a572aaa8436/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f58624e7a2f67656d696e693f7374796c653d666c61742d737175617265)](https://camo.githubusercontent.com/59724e6687b9ec6a9b6f514ce16c123a4234146373c3e98b71e90a572aaa8436/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f58624e7a2f67656d696e693f7374796c653d666c61742d737175617265)

Google Gemini API client with OAuth2 authentication
===================================================

[](#google-gemini-api-client-with-oauth2-authentication)

Motivation
----------

[](#motivation)

Other libraries rely on the `generativelanguage.googleapis.com` API, which misses some models. For example, the newly-introduced "Gemini Experimental" model, which is free (!) cannot be accessed through that API. This library solves that issue.

Note

The Gemini Experimental API is not guaranteed to last forever. If you are using a model that is available on the `generativelanguage.googleapis.com` API, you can use this library to access it as well.

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

[](#installation)

```
composer require xbnz/gemini
```

Prerequisites
-------------

[](#prerequisites)

### Creating a service account on Google Cloud

[](#creating-a-service-account-on-google-cloud)

1. Go to the [Google Cloud Console](https://console.cloud.google.com/)
2. Go to [IAM &amp; Admin](https://console.cloud.google.com/iam-admin/)
3. Go to [Service Accounts](https://console.cloud.google.com/iam-admin/serviceaccounts)
4. Click on your project
5. Click on "Create Service Account" if you don't have one yet
6. Give it a name and click on "Create"
7. Click on "Done"
8. Go back into the service account you just created
9. Click on "Add Key" and create a JSON key. The file will be downloaded to your computer
10. Grab the necessary information from the JSON file:
    - `client_email`
    - `private_key`

Getting started
---------------

[](#getting-started)

### Sample application

[](#sample-application)

Here is a [sample Laravel command](https://github.com/XbNz/gemini-example/blob/main/app/Console/Commands/GeminiCommand.php) that uses this library. The [service provider](https://github.com/XbNz/gemini-example/blob/main/app/Providers/AppServiceProvider.php) is where the interfaces are bound to concretes.

### Registering to the dependency injection container (optional)

[](#registering-to-the-dependency-injection-container-optional)

```
// Laravel example

namespace App\Providers;

clsss AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->bind(GoogleOAuth2Interface::class, function (Application $app) {
            return new GoogleOAuth2Service(
                logger: $app->make(LoggerInterface::class)
            );
        });

        $this->app->bind(GoogleAIPlatformInterface::class, function (Application $app) {
            return new GoogleAIPlatformService(
                (new GoogleAIPlatformConnector(
                    $app->make('config')->get('services.google_ai_platform.project_id'),
                    $app->make('config')->get('services.google_ai_platform.region'),
                ))->authenticate(
                    new TokenAuthenticator(
                        $app->make(GoogleOAuth2Interface::class)->token(
                            new TokenRequestDTO(
                                googleServiceAccount: new GoogleServiceAccount(
                                    $app->make('config')->get('services.google_ai_platform.client_email'),
                                    $app->make('config')->get('services.google_ai_platform.private_key'),
                                ),
                                scope: 'https://www.googleapis.com/auth/cloud-platform',
                                issuedAt: CarbonImmutable::now(),
                                expiration: CarbonImmutable::now()->addHour()
                            )
                        )->accessToken
                    )
                ),
                $app->make('log')
            );
        });
    }
}
```

### Using the AIPlatform service for single or multi-turn conversations

[](#using-the-aiplatform-service-for-single-or-multi-turn-conversations)

```
namespace App\Console\Commands;

class SomeCommand
{
    public function __construct(
        private readonly AIPlatformInterface $aiPlatformService
    ) {}

    public function handle(): void
    {
        $response = $this->aiPlatformService->generateContent(
            new GenerateContentRequestDTO(
                'publishers/google/models/gemini-experimental',
                Collection::make([
                    new ContentDTO(
                        Role::User,
                        Collection::make([
                            new TextPart('Explain what is happening in the image'),
                            new BlobPart(
                                'image/jpeg',
                                'base64 image...',
                            )
                        ])
                    ),
                    new ContentDTO(
                        Role::Model,
                        Collection::make([
                            new TextPart('Sure! This is an image of a cat.'),
                        ]),
                    ),
                    new ContentDTO(
                        Role::User,
                        Collection::make([
                            new TextPart('What color is the cat?'),
                        ]),
                    ),
                    // and so on...
                ])
                Collection::make([
                    new SafetySettings(HarmCategory::HarmCategoryHarassment, SafetyThreshold::BlockOnlyHigh),
                    new SafetySettings(HarmCategory::HarmCategoryHateSpeech, SafetyThreshold::BlockOnlyHigh),
                    new SafetySettings(HarmCategory::HarmCategorySexuallyExplicit, SafetyThreshold::BlockOnlyHigh),
                    new SafetySettings(HarmCategory::HarmCategoryDangerousContent, SafetyThreshold::BlockOnlyHigh),
                ]),
                systemInstructions: Collection::make([
                    new TextPart('Your instructions here...'),
                ]),
                generationConfig: new GenerationConfig(...) // Optional
            )
        );

        if ($response->finishReason->consideredSuccessful() === false) {
            // Handle the model not being able to generate content (probably due to unsafe content)
        }

        // Do something with the healthy response
        $response->usage->promptTokenCount;
        $modelResponse = $response
            ->content
            ->parts
            ->sole(fn(PartContract $part) => $part instanceof TextPart) // There should only be one TextPart::class in a model response (for now)
            ->text;
    }
}
```

Note

You may new up the classes directly if you don't want to use a dependency injection container

Note

You may serialize and store the TextPart::class responses from the model in your database. This will allow you to conduct a persistent chat session with the model, resembling something like teh ChatGPT interface.

Core concepts
-------------

[](#core-concepts)

### Extensible authentication

[](#extensible-authentication)

The Google `aiplatform.googleapis.com` API allows several forms of authentication. This library is opinionated toward using the `access_token` derived from your service account. However, the underlying HTTP client of this library (SaloonPHP) allows "Connector" classes to be extended with any authenticator before being newed up. As a result, you may create your own Saloon authentication strategy and pass it to the constructor:

```
namespace App\Providers;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->bind(GoogleAIPlatformInterface::class, function (Application $app) {
            return new GoogleAIPlatformService(
                (new GoogleAIPlatformConnector(...))->authenticate(new MyCustomAuthenticator),
            );
        });
    }
}
```

### Bearer token authentication

[](#bearer-token-authentication)

The provided `GoogleOAuthInterface::token()` method allows you to fetch a new token for bearer authentication. Do keep in mind that if you use this tool for authenticating the AIPlatform, the process generates a new token every time the method is called which may or may not be desirable.

#### Caching your token until expiry (Laravel example)

[](#caching-your-token-until-expiry-laravel-example)

This package does not provide a caching mechanism – for example using the PSR cache interface – due to the dead simple cache integration of most modern frameworks. Here is a Laravel example:

```
namespace App\Providers;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
          $this->app->bind(GoogleAIPlatformInterface::class, function (Application $app) {
            return new GoogleAIPlatformService(
                (new GoogleAIPlatformConnector(...))->authenticate(
                    new TokenAuthenticator(
                        $app->make('cache')->remember(
                            'google_api_platform_token',
                            CarbonImmutable::now()->addMinutes(60),
                            function () use ($app) {
                                return $app->make(GoogleOAuth2Interface::class)->token(
                                    new TokenRequestDTO(
                                        googleServiceAccount: new GoogleServiceAccount(
                                            $app->make('config')->get('services.google_ai_platform.client_email'),
                                            $app->make('config')->get('services.google_ai_platform.private_key'),
                                        ),
                                        scope: 'https://www.googleapis.com/auth/cloud-platform',
                                        issuedAt: CarbonImmutable::now(),
                                        expiration: CarbonImmutable::now()->addHour()
                                    )
                                )->accessToken;
                            }
                        ),
                    )
                ),
                $app->make('log')
            );
        });
    }
}
```

### Logging and exception handling

[](#logging-and-exception-handling)

### Providing your own PSR-compatible logger

[](#providing-your-own-psr-compatible-logger)

This library uses the PSR logger interface for logging. You may provide your own logger by passing it to the constructor of the service:

```
namespace App\Console\Commands;

class SomeCommand
{
    public function handle(): void
    {
        $service = new GoogleAIPlatformService(
            new GoogleAIPlatformConnector(...),
            new MyCustomLogger
        );

        try {
            $response = $service->generateContent(...);
        } catch (GoogleAIPlatformException $e) {
            // Handle the exception
        }

        // At this point, the logger will have logged the exception
    }
}
```

The same functionality exists on the OAuth2 service.

### Lifecycle hooks for requests and responses

[](#lifecycle-hooks-for-requests-and-responses)

This is not recommended for basic use cases. However, APIs change and maintainers are lazy. If Google adds a new field to a response which I cannot work on, you are free to hook into the response and create your own DTOs if you don't want to make a PR.

```
namespace App\Console\Commands;

class SomeCommand
{
    public function __construct(
        private readonly GoogleAIPlatformInterface $aiPlatform
    ) {}

    public function handle(): void
    {
        $this->aiPlatform->generateContent(
            requestDto: ...,
            beforeRequest: function (Request $request) {
                $request->headers()->merge([
                    'X-Custom-Header' => 'Value'
                ]);

                return $request;
            },
            afterResponse: function (Response $response) {
                // Return your own DTO or do something with the response

                return $response;
            }
        )
    }
}
```

### Retrying failed requests

[](#retrying-failed-requests)

When using free Gemini models, strict rate limits are imposed. You may decide to retry when 429 responses are encountered.

#### Prerequisites

[](#prerequisites-1)

A Guzzle retry middleware is not provided. You may implement your own or use a library of your choice. Example:

```
composer require caseyamcl/guzzle_retry_middleware
```

```
namespace App\Providers;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->bind(GoogleAIPlatformInterface::class, function (Application $app) {
            $connector = new GoogleAIPlatformConnector(...);
            $connector->authenticate(...)
            $connector->sender()->getHandlerStack()->push(
                GuzzleRetryMiddleware::factory([
                    'max_retry_attempts' => 5,
                    'retry_on_status' => [429],
                ])
            )

            return new GoogleAIPlatformService(
                $connector
            );
        });
    }
}
```

Testing
-------

[](#testing)

This library provides fake implementations for testing purposes. For example, you may use the `GoogleOAuth2ServiceFake::class` like so:

### Calling code

[](#calling-code)

```
namespace App\Console\Commands;

use XbNz\Gemini\OAuth2\GoogleOAuth2Interface;

class SomeCommand
{
    public function __construct(
        private readonly GoogleOAuth2Interface $googleOAuth2Service
    ) {}

    public function handle(): void
    {
        $response = $this->googleOAuth2Service->token(...);
    }
}
```

### Test code

[](#test-code)

```
namespace Tests\Feature;

use Tests\TestCase;
use XbNz\Gemini\OAuth2\DataTransferObjects\Requests\TokenRequestDTO;
use XbNz\Gemini\OAuth2\GoogleOAuth2ServiceFake;

class SomeCommandTest extends TestCase
{
    public function test_it_works(): void
    {
        // Swapping the real service with the fake one in the Laravel container
        $this->app->swap(GoogleOAuth2Interface::class, $fake = new GoogleOAuth2ServiceFake);

        // Basic testing helpers
        $fake->alwaysReturnToken(...);
        $fake->assertTokenRequestCount(...);

        // Asserting against requests
        $fake->assertTokenRequest(function (TokenRequestDTO) {
            return $dto->grantType === 'urn:ietf:params:oauth:grant-type:jwt-bearer';
        });
    }
}
```

Note

The same concept can be applied to the AIPlatform service. The fake implementation is called `GoogleAIPlatformServiceFake::class` and provides similar test assertions

###  Health Score

33

—

LowBetter than 75% of packages

Maintenance41

Moderate activity, may be stable

Popularity11

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity62

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

Recently: every ~59 days

Total

6

Last Release

488d ago

Major Versions

0.2.0 → 1.0.02024-05-23

1.0.0 → 2.0.02025-01-12

PHP version history (2 changes)0.1.0PHP ^8.3

2.0.0PHP ^8.4

### Community

Maintainers

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

---

Top Contributors

[![XbNz](https://avatars.githubusercontent.com/u/12668624?v=4)](https://github.com/XbNz "XbNz (34 commits)")

---

Tags

apigoogleaiGeminiexperimentalaiplatformaiplatform.googleapis.com

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/xbnz-google-gemini-api/health.svg)

```
[![Health](https://phpackages.com/badges/xbnz-google-gemini-api/health.svg)](https://phpackages.com/packages/xbnz-google-gemini-api)
```

###  Alternatives

[gemini-api-php/client

API client for Google's Gemini API

216221.4k5](/packages/gemini-api-php-client)[hosseinhezami/laravel-gemini

A production-ready Laravel package to integrate with the Google Gemini API. Supports text, image, video, audio, long-context, structured output, files, caching, function-calling and understanding capabilities.

14010.8k1](/packages/hosseinhezami-laravel-gemini)[gemini-api-php/laravel

Gemini API client for Laravel

8915.7k](/packages/gemini-api-php-laravel)[deepseek-php/deepseek-php-client

deepseek PHP client is a robust and community-driven PHP client library for seamless integration with the Deepseek API, offering efficient access to advanced AI and data processing capabilities.

47073.9k5](/packages/deepseek-php-deepseek-php-client)[ozankurt/google-analytics

Laravel Google Analytics

7616.7k](/packages/ozankurt-google-analytics)

PHPackages © 2026

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