PHPackages                             shipstream/ups-rest-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. [API Development](/categories/api)
4. /
5. shipstream/ups-rest-php-sdk

ActiveLibrary[API Development](/categories/api)

shipstream/ups-rest-php-sdk
===========================

PHP SDK for UPS REST API

2.3.4(10mo ago)2253.7k↓13.4%10Apache-2.0PHPPHP ^8.0CI passing

Since Oct 26Pushed 3mo ago4 watchersCompare

[ Source](https://github.com/ShipStream/ups-rest-php-sdk)[ Packagist](https://packagist.org/packages/shipstream/ups-rest-php-sdk)[ RSS](/packages/shipstream-ups-rest-php-sdk/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (6)Versions (21)Used By (0)

UPS REST PHP SDK
================

[](#ups-rest-php-sdk)

A PHP SDK for the UPS REST API, brought to you by [ShipStream](https://shipstream.io).

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

[](#installation)

```
composer require shipstream/ups-rest-php-sdk
```

**Note:** The latest version supports PHP 8.2 or above. For PHP 7.4 support, please append the `^1.0` version constraint to the above command.

Basic Usage
-----------

[](#basic-usage)

Create a UPS Client instance using a configuration object:

```
$config = new \ShipStream\Ups\Config([
    // Whether to send the requests to the UPS Customer Integration Environment instead of the production environment.
    // Optional, defaults to false.
    'use_testing_environment' => true,
    // The grant type to use for obtaining an access token. Available options: 'client_credentials', 'authorization_code'.
    // Optional, defaults to 'client_credentials'.
    'grant_type' => \ShipStream\Ups\Config::GRANT_TYPE_CLIENT_CREDENTIALS,
    // Your Client ID obtained from UPS Developer portal.
    'client_id' => 'your_client_id',
    // Your Client Secret obtained from UPS Developer portal.
    'client_secret' => 'your_client_secret',
    // The URL to redirect to after authenticating with UPS using Authorization Code flow.
    // Required only when using Authorization Code flow, defaults to an empty string.
    'redirect_uri' => 'https://example.com/oauth/callback',
]);

$client = \ShipStream\Ups\ClientFactory::create($config);
```

The Client object contains methods for every endpoint available in the [UPS OpenAPI definition files](./openapi) with PHPDoc comments that describe the parameters and return types, as well as any thrown exceptions. Method names for each endpoint is based on the `operationId` property of the OpenAPI specification.

Here's an example using the Tracking API:

```
try {
    $response = $client->getSingleTrackResponseUsingGET('1ZXXXXXXXXXXXXXXXX', $queryParams = [], $headers = [
        'transId' => 'Track-1ZXXXXXXXXXXXXXXXX-'.time(),
        'transactionSrc' => 'testing'
    ]);
    // Do something with the response
} catch (
    \ShipStream\Ups\Api\Exception\GetSingleTrackResponseUsingGETNotFoundException |
    \ShipStream\Ups\Api\Exception\GetSingleTrackResponseUsingGETBadRequestException |
    \ShipStream\Ups\Api\Exception\GetSingleTrackResponseUsingGETInternalServerErrorException |
    \ShipStream\Ups\Api\Exception\GetSingleTrackResponseUsingGETServiceUnavailableException $e
) {
    $errors = $e->getErrorResponse()->getResponse()->getErrors();
    $errors = array_map(fn ($error) => $error->getMessage(), $errors);
    echo 'Error: '.implode(' - ', $errors)."\n";
} catch (\ShipStream\Ups\Api\Exception\UnexpectedStatusCodeException $e) {
    echo "Unexpected response received from UPS: {$e->getMessage()}\n";
} catch (\ShipStream\Ups\Exception\AuthenticationException $e) {
    echo "Authentication error: {$e->getMessage()}\n";
}
```

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

[](#authentication)

### Client Credentials

[](#client-credentials)

Using Client Credentials flow works out of the box and requires no additional steps as the access token generation and refresh is handled internally.

### Authorization Code

[](#authorization-code)

To start using the Authorization Code flow set `grant_type` config to `Config::GRANT_TYPE_AUTHORIZATION_CODE`, then call the `authorizeClient` endpoint and redirect the user to the returned login URL:

```
$response = $client->authorizeClient([
    'client_id' => $client->getConfig()->getClientId(),
    'redirect_uri' => $client->getConfig()->getRedirectUri(),
    'response_type' => 'code'
]);

// Redirect the user to the login page
header('Location: ' . $response->getLocation());
```

The user will be redirected back to your app after login with the authorization code that will be used to generate an access token:

```
$client->exchangeAuthorizationCode($_GET['code']);
```

The access token refresh will be handled internally so long that the refresh token is still valid. You can check if the client is authenticated at any time by calling `$client->getAccessToken()` which attempts to retrieve the access token from the cache and refresh it if it has already expired, otherwise it throws an `AuthenticationException`.

#### Preventing race conditions when refreshing expired tokens

[](#preventing-race-conditions-when-refreshing-expired-tokens)

When multiple PHP processes attempt to call an endpoint while the access token is expired, a race condition may occur resulting in one process refreshing the token successfully, while the other processes will fail with `Invalid Refresh Token` or a similar error. To help prevent this, locking can be enabled by passing a third argument to Client factory that can be any class implementing the [`AccessTokenLock`](./src/Authentication/AccessTokenLock.php) interface. A built-in implementation called [`FileAccessTokenLock`](./src/Authentication/FileAccessTokenLock.php) is provided for convenience, it takes a writable file path and uses it for locking. Example:

```
$client = \ShipStream\Ups\ClientFactory::create(
    $config,
    null,
    new \ShipStream\Ups\Authentication\FileAccessTokenLock('/tmp/ups-sdk-token.lock')
);
```

### Caching Access Tokens

[](#caching-access-tokens)

The library uses an in-memory cache for access tokens by default which is useful when doing quick tests, but for a production environment you'd want to use something like Redis or a filesystem cache to avoid doing round trips to generate an access token on every request. To achieve this, the Client factory accepts a second parameter which can be any object that implements the [`AccessTokenCache`](./src/Authentication/AccessTokenCache.php) interface. For example, a Redis implementation could look like this:

```
class RedisAccessTokenCache implements \ShipStream\Ups\Authentication\AccessTokenCache
{
    private $predis;

    public function __construct(\Predis\Client $predis)
    {
        $this->predis = $predis;
    }
    public function save(\ShipStream\Ups\Authentication\AccessToken $accessToken)
    {
        $clientId = $accessToken->getClientId();
        $accessTokenKey = "access_token:$clientId";
        $this->predis->set($accessTokenKey, serialize($accessToken));
    }
    public function retrieve(string $clientId): ?\ShipStream\Ups\Authentication\AccessToken
    {
        $accessTokenKey = "access_token:$clientId";
        $cachedAccessToken = $this->predis->get($accessTokenKey);
        if ($cachedAccessToken !== false) {
            return unserialize($cachedAccessToken, ['allowed_classes' => [\ShipStream\Ups\Authentication\AccessToken::class]]);
        }
        return null;
    }
}
$client = \ShipStream\Ups\ClientFactory::create($config, new RedisAccessTokenCache(new \Predis\Client()));
```

Using a custom HTTP Client
--------------------------

[](#using-a-custom-http-client)

If you wish to customize how HTTP requests are made, perhaps for logging or to add additional headers, the Client factory supports a third parameter that can be any HTTP Client that implements the [PSR-18](https://www.php-fig.org/psr/psr-18/) standard. E.g.:

```
$client = \ShipStream\Ups\ClientFactory::create($config, null, new \GuzzleHttp\Client());
```

Note that the HTTP Client **must not** throw exceptions for 4xx and 5xx responses, as those should be handled by the SDK.

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

[](#development)

The classes under the `ShipStream\Ups\Api` namespace are all generated using [janephp](https://jane.readthedocs.io/en/latest/index.html).

**ARM/Docker Setups:**
Run the `generate.sh` script to regenerate the classes when needed.

**AMD64 (WSL/Linux) Setups:**
Run the `generate-amd64.sh` script to regenerate the classes when needed.

###  Health Score

49

—

FairBetter than 95% of packages

Maintenance69

Regular maintenance activity

Popularity41

Moderate usage in the ecosystem

Community18

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 84.1% 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 ~32 days

Total

20

Last Release

314d ago

Major Versions

1.5.0 → 2.3.02024-05-27

1.6.0 → 2.3.12024-05-31

1.6.1 → 2.3.22024-08-30

1.6.2 → 2.3.32025-02-10

1.x-dev → 2.3.42025-07-08

PHP version history (3 changes)1.0.0PHP ^7.4 || ^8.0

1.3.0PHP ^7.4

2.0.0PHP ^8.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/38738?v=4)[Colin Mollenhour](/maintainers/colinmollenhour)[@colinmollenhour](https://github.com/colinmollenhour)

---

Top Contributors

[![elidrissidev](https://avatars.githubusercontent.com/u/67818913?v=4)](https://github.com/elidrissidev "elidrissidev (53 commits)")[![colinmollenhour](https://avatars.githubusercontent.com/u/38738?v=4)](https://github.com/colinmollenhour "colinmollenhour (6 commits)")[![RickKukiela](https://avatars.githubusercontent.com/u/3813238?v=4)](https://github.com/RickKukiela "RickKukiela (2 commits)")[![djfrailey](https://avatars.githubusercontent.com/u/5817088?v=4)](https://github.com/djfrailey "djfrailey (1 commits)")[![zambodaniel](https://avatars.githubusercontent.com/u/3462880?v=4)](https://github.com/zambodaniel "zambodaniel (1 commits)")

---

Tags

rest-apishippingupswms

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/shipstream-ups-rest-php-sdk/health.svg)

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

###  Alternatives

[meilisearch/meilisearch-php

PHP wrapper for the Meilisearch API

74513.7M114](/packages/meilisearch-meilisearch-php)[jolicode/slack-php-api

An up to date PHP client for Slack's API

2534.4M12](/packages/jolicode-slack-php-api)[php-heroku-client/php-heroku-client

A PHP client for the Heroku Platform API

24404.8k4](/packages/php-heroku-client-php-heroku-client)[wol-soft/php-json-schema-model-generator

Creates (immutable) PHP model classes from JSON-Schema files including all validation rules as PHP code

81109.2k3](/packages/wol-soft-php-json-schema-model-generator)[jolicode/harvest-php-api

An up to date PHP client for Harvest's API

2259.9k](/packages/jolicode-harvest-php-api)[jikan/jikan-php

PHP client for jikan rest

291.1k](/packages/jikan-jikan-php)

PHPackages © 2026

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