PHPackages                             kbart/amazon-ads-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. [API Development](/categories/api)
4. /
5. kbart/amazon-ads-sdk

ActiveLibrary[API Development](/categories/api)

kbart/amazon-ads-sdk
====================

Amazon Ads API SDK for Laravel

v1.0.0(3mo ago)08Apache-2.0PHPPHP ^8.2CI passing

Since Apr 2Pushed 2mo agoCompare

[ Source](https://github.com/Braindea7/amazon-ads-sdk)[ Packagist](https://packagist.org/packages/kbart/amazon-ads-sdk)[ RSS](/packages/kbart-amazon-ads-sdk/feed)WikiDiscussions main Synced 4w ago

READMEChangelogDependencies (8)Versions (2)Used By (0)

Laravel Amazon Ads SDK
======================

[](#laravel-amazon-ads-sdk)

[![Run Tests](https://github.com/Braindea7/amazon-ads-sdk/actions/workflows/run-tests.yml/badge.svg)](https://github.com/DEIN_GITHUB_NAME/amazon-ads-sdk/actions/workflows/run-tests.yml)

A developer-friendly (DX) Laravel package for integrating the **[Amazon Ads API](https://advertising.amazon.com/API/docs/en-us/reference/amazon-ads/overview)**.

This package combines the type safety of a generated OpenAPI SDK with the convenience of dynamic Laravel proxy routes. It handles the complete authentication (LWA Token Refresh), rate limiting, and DTO hydration for you.

💎 Features
----------

[](#-features)

- **Magic LWA Token Manager:** Fully automatically fetches and refreshes Access Tokens via Amazon "Login with Amazon" and caches them securely in Redis/Cache.
- **Smart Retries:** Catches rate limits (`429`) and server errors (`5xx`) and automatically retries requests using exponential backoff.
- **Multi-Seller Ready:** Authentication is handled dynamically via the `{seller}` route parameter.
- **Debugging &amp; Agent:** Easy control over Guzzle debug output and User-Agent headers.
- **Dual Architecture:**
    - **Direct SDK Usage (via Facade):** Full autocompletion and type safety for backend jobs (cron jobs, queues).
    - **Dynamic SDK Proxy:** A universal interface (`/api/amazon-ads/sdk/{seller}/...`) for the frontend (Vue/React) with fully automatic DTO routing.
- **Self-Documenting API:** An info route (`/api/amazon-ads/sdk/{seller}/info/...`) that resolves the entire Amazon Ads API, including Enums and Schemas, using PHP Reflection.

---

⚡ Installation
--------------

[](#-installation)

1. **Install the package via Composer**

```
composer require kbart/amazon-ads-sdk

```

2. **Publish the configuration file**

```
php artisan vendor:publish --tag="amazon-ads-config"

```

3. **Add your default credentials to your `.env` file**

```
AMAZON_ADS_DEFAULT_CLIENT_ID="amzn1.application-oa2-client.xxxx"
AMAZON_ADS_DEFAULT_CLIENT_SECRET="amzn1.oa2-client.v1.xxxx"
AMAZON_ADS_DEFAULT_REFRESH_TOKEN="Atzr|xxxx"
AMAZON_ADS_DEFAULT_REGION="EU" # EU, NA, or FE
AMAZON_ADS_DEFAULT_PROFILE_ID="xxx"
```

4. **Routes &amp; Middleware**

By default, the package registers the SDK routes under the prefix `api/amazon-ads/sdk/{seller}`. To use the SDK routes, you must manually load them in your `routes/api.php`. You can also assign your own middleware:

```
use KBart\AmazonAds\AmazonAds;
use App\Http\Middleware\Authenticate;

// Registers the routes under api/amazon-ads/sdk/{seller}/...
AmazonAds::routes([
    'middleware' => [Authenticate::class, 'your-custom-access-check'],
]);
```

*(If you register the routes in your `web.php`, you must either include the 'api' middleware or exclude the routes from the CSRF token check in your `bootstrap/app.php`!)*

---

Usage
-----

[](#usage)

### 1. The SdkProxy (Recommended)

[](#1-the-sdkproxy-recommended)

The `SdkProxyController` receives HTTP requests, forwards them to the corresponding classes of the generated SDK, and returns the result as clean JSON.

**Example Request (POST):**Request to your local Laravel endpoint to fetch keywords.

```
POST /api/amazon-ads/sdk/{seller}/SponsoredProduct/Keywords/listSponsoredProductsKeywords
Content-Type: application/json
```

```
{
    "sponsoredProductsListSponsoredProductsKeywordsRequestContent": {
        "maxResults": 100,
        "stateFilter": {
            "include": [
                "ENABLED",
                "PAUSED"
            ]
        }
    }
}
```

*(The `AmazonAdsExecutor` recognizes that the `sponsoredProductsListSponsoredProductsKeywordsRequestContent` parameter requires a complex SDK object and safely casts your JSON array into this DTO before calling the SDK method.)*

#### A. Docs / Info Route (Self-Documenting API)

[](#a-docs--info-route-self-documenting-api)

Want to know which APIs are available and what the payload should look like? Send a `GET` request to the info routes:

- **All Verticals:** `GET /api/amazon-ads/sdk/{seller}/info`
- **All Resources (e.g., SponsoredProducts):** `GET /api/amazon-ads/sdk/{seller}/info/sponsored-products`
- **All Methods (e.g., Campaigns):** `GET /api/amazon-ads/sdk/{seller}/info/sponsored-products/campaigns`

The response will show you exactly which parameters are expected, whether a complex DTO needs to be sent, and which Enum values are allowed!

### 2. The Native Proxy

[](#2-the-native-proxy)

If you want to bypass the SDK completely and instead call the Amazon endpoints directly using Guzzle/Laravel HTTP, use the `ProxyController`.

**Example Request (POST):**

```
POST /api/amazon-ads/proxy/sp/keywords/list?seller={seller}
Content-Type: application/json
X-Amazon-Profile-Id: 1234567890
```

```
{
    "maxResults": 100,
    "stateFilter": {
        "include":[
            "ENABLED"
        ]
    }
}
```

### 3. Direct Usage in PHP (Facades)

[](#3-direct-usage-in-php-facades)

If you are building complex calculations or nightly synchronizations, you should use the generated SDK classes directly. You can comfortably use the `AmazonAdsFactory` facade for this. The package handles token injection and rate-limit retries in the background!

```
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use KBart\AmazonAds\Facades\AmazonAdsSdk;
use KBart\AmazonAds\Auth\AmazonAdsCredentials;
use KBart\AmazonAds\Generated\SponsoredProducts\Api\CampaignsApi;

// The facade takes care of EVERYTHING:
// Token Refresh, Retries, Rate Limits AND the automatic
// hydration of the array into complex Amazon DTOs!
class CustomAmazonController extends Controller
{
    // Via Request: Pass the Request, as well as the Namespace, desired Api Class and Method.
    public function createCampaignWithRequest(Request $request)
    {
        return $this->handleApiCall(function () use ($request) {
            return AmazonAdsSdk::execute(
                request: $request,
                namespace: 'SponsoredProduct',
                apiClass: CampaignsApi::class,
                method: 'listSponsoredProductsCampaigns'
            );
        });
    }

    // Via Payload: Pass the Payload, as well as the Namespace, desired Api Class and Method.
    public function createCampaignWithArray(array $payload)
    {
        return $this->handleApiCall(function () use ($payload) {
            $credentials = AmazonAdsCredentials::fromArray($payload);

            return AmazonAdsSdk::executeWithCredentials(
                credentials: $credentials,
                namespace: 'SponsoredProduct',
                apiClass: CampaignsApi::class,
                method: 'createCampaigns',
                payload: $payload
            );
        });
    }
}
```

---

👨‍💼 Advanced
------------

[](#‍-advanced)

### 1. Custom Credentials Resolver

[](#1-custom-credentials-resolver)

By default, the package uses the `.env` variables. If you want to store your seller data in a database, for example, you can define your own credentials resolver in the `AppServiceProvider` of your Laravel application.

From now on, the package will always call this logic when executing API calls!

```
// in app/Providers/AppServiceProvider.php

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Carbon;
use Illuminate\Validation\Rule;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use KBart\AmazonAds\AmazonAds;
use KBart\AmazonAds\Auth\AmazonAdsCredentials;
use App\Models\Seller;

public function boot(): void
{
    AmazonAds::resolveCredentialsUsing(function (Request $request) {
        $request->mergeIfMissing([
            'seller' => $request->route('seller', $request->query('seller', $request->input('seller', null))),
            'endpoint' => 'EU',
            'countryCode' => 'DE',
        ]);

        $validated = $request->validate([
            'seller'     => [
                'required',
                'string',
                Rule::exists(Seller::class, 'seller'),
            ],
            'endpoint' => ['required', 'string'],
            'countryCode' => ['required', 'string'],
        ]);

        $seller = Seller::where('seller', $validated['seller'])
            ->whereHas('logins', function ($query) use ($validated) {
                $query->where('endpoint', $validated['endpoint'])
                    ->whereHas('profiles', function ($q) use ($validated) {
                        $q->where('countryCode', $validated['countryCode']);
                    });
            })
            ->with([
                'logins' => function ($query) use ($validated) {
                    $query->where('endpoint', $validated['endpoint'])
                        ->limit(1)
                        ->with([
                            'profiles' => function ($q) use ($validated) {
                                $q->where('countryCode', $validated['countryCode'])
                                    ->limit(1);
                            },
                        ]);
                },
            ])
            ->first();

        if (empty($seller)) {
            Log::error("Doesn't find Seller {$validated['seller']} with Login for endpoint {$validated['endpoint']} or profile for {$validated['countryCode']}, in Database.");
            throw new \InvalidArgumentException("Can't find Sellerprofile {$validated['seller']}");
        }

        $login = $seller->logins->first();
        $profile = $login->profiles->first();

        if (! empty($login->clientSecretExpiry)) {
            if (Carbon::parse($login->clientSecretExpiry)->subDays(3)->lessThanOrEqualTo(now())) {
                Log::error("clientSecret of {$seller->seller} is very close to expire!", [
                    'expiresAt' => $login->clientSecretExpiry,
                    'hoursLeft' => Carbon::parse($login->clientSecretExpiry)->diffInHours(now()),
                ]);
            } elseif (Carbon::parse($login->clientSecretExpiry)->subDays(14)->lessThanOrEqualTo(now())) {
                Log::info("clientSecret of {$seller->seller} is about to expire!", [
                    'expiresAt' => $login->clientSecretExpiry,
                    'daysLeft' => Carbon::parse($login->clientSecretExpiry)->diffInDays(now()),
                ]);
            }
        }

        return new AmazonAdsCredentials(
            clientId: $login->clientId,
            clientSecret: $login->clientSecret,
            refreshToken: $login->refreshToken,
            region: $login->endpoint,
            profileId: $profile->profileId,
        );
    });
}
```

### 2. Set a custom user-agent

[](#2-set-a-custom-user-agent)

Amazon does not strictly require a specific User-Agent; it can be determined by you and adjusted in the config if necessary.

```
'settings' => [
    'user-agent' => 'Your-User-Agent/1.0.0/PHP',
]
```

### 3. Caching &amp; TTL Configuration

[](#3-caching--ttl-configuration)

In `config/amazon-ads.php`, specific TTL values for caching endpoints can be defined.

```
'cache-ttl' => [
    'catalogItemsV20220401' => [
        'getCatalogItem'     => 3600, // cache for 1 hour
        'searchCatalogItems' => 600,  // cache for 10 minutes
    ],
    'productPricingV0' => [
        'getPricing'         => 300,  // cache for 5 minutes
    ],
]
```

---

Enable Debugging
----------------

[](#enable-debugging)

If you want to enable debugging for the SDK, adjust the corresponding parameters in the config.

```
'settings' => [
    'debug' => true,
    'debugFile' => base_path('storage/logs/amazon-ads-sdk.log'),
]
```

---

🛠️ SDK Generation (Build Process)
---------------------------------

[](#️-sdk-generation-build-process)

This SDK uses the official [OpenAPI Specifications](https://swagger.io/specification/) from Amazon to always remain 100% type-safe and up to date. The required `.json` and `.yaml` specification files are now located directly within your package in the `./resources/openapi/` directory. An automated pipeline based on Node.js and PHP has been built, generating ready-to-use classes for you at the push of a button. This utilizes the official [openapi-generator-cli](https://github.com/OpenAPITools/openapi-generator-cli) tool. The build script also automatically fixes known Amazon OpenAPI bugs and cleans up the endpoints.

### Prerequisites

[](#prerequisites)

Ensure that you have **Node.js** and **npm** installed on your system. Before running for the first time, install the necessary dependencies in the root directory of the package:

```
npm install

```

### 1. Regenerate all endpoints

[](#1-regenerate-all-endpoints)

If you want to bring the entire SDK up to date, run this command:

```
npm run build:all

```

*(This is equivalent to `npm run clean && npm run generate`)*

**What happens in the background?**

1. The `src/Generated` folder is completely emptied.
2. The script loads the OpenAPI files directly from the local `./resources/openapi/` directory.
3. A pre-processor script cleans the OpenAPI spec files in `.json` format and removes problematic Content-Types like `application/json` if `application/vnd...` is present.
4. The `openapi-generator-cli` generates all Models (DTOs) and APIs.
5. All redundant boilerplate files are cleaned up (`cleanup.js`). *(Uses rimraf under the hood)*.
6. A PHP script (`generate_api_map.php`) scans the new classes and fully automatically creates the `src/Laravel/amazon_api_map.php` file, which acts as a lightning-fast registry.
7. A post-processor script fixes duck-typing and import issues in the generated classes `ObjectSerializer.php` and `FormDataProcessor.php`.

### 2. Update a single endpoint

[](#2-update-a-single-endpoint)

If Amazon has only updated one area (e.g., `SponsoredProduct`), you can specifically target individual endpoints without rebuilding everything:

```
npm run generate -- SponsoredProduct

```

*(This **only** updates the SponsoredProduct classes and automatically regenerates the API map at the end, without deleting other endpoints)*.

### 3. Add a new endpoint

[](#3-add-a-new-endpoint)

Has Amazon released a new API? No problem:

1. Download the specification file from Amazon and save it in your `./resources/openapi/` folder (e.g., as `NewApi.json`).
2. Open the `generate-apis.js` file in the root directory.
3. Add a new entry to the `apis` array, referencing the local file path: `{ name: 'GreatNewApi', input: './resources/openapi/NewApi.json' }`
4. Run `npm run generate -- GreatNewApi`.
5. Done! The API is now immediately available as a PHP class and is automatically registered in the Proxy Controller.

📄 License
---------

[](#-license)

This project is licensed under the Apache License 2.0.

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance83

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 75% 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

Unknown

Total

1

Last Release

90d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/3661424cb18ceafc0fbb7275362bdeda7cad5271b0be8fed764eb3f14f6dbb2b?d=identicon)[KBart](/maintainers/KBart)

---

Top Contributors

[![Braindea7](https://avatars.githubusercontent.com/u/31728352?v=4)](https://github.com/Braindea7 "Braindea7 (3 commits)")[![Lacritz](https://avatars.githubusercontent.com/u/13005749?v=4)](https://github.com/Lacritz "Lacritz (1 commits)")

###  Code Quality

TestsPHPUnit

Code StyleECS

### Embed Badge

![Health badge](/badges/kbart-amazon-ads-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/kbart-amazon-ads-sdk/health.svg)](https://phpackages.com/packages/kbart-amazon-ads-sdk)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M126](/packages/roots-acorn)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M129](/packages/laravel-pulse)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

77022.3M143](/packages/laravel-mcp)[fleetbase/core-api

Core Framework and Resources for Fleetbase API

1235.9k20](/packages/fleetbase-core-api)[spatie/laravel-export

Create a static site bundle from a Laravel app

674146.0k6](/packages/spatie-laravel-export)

PHPackages © 2026

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