Search by

assets-pro / php-sdk

orpheusohms

Typed AssetsPro API client with optional Laravel integration.

Package info

github.com/opheus2/assetspro-php-sdk

pkg:composer/assets-pro/php-sdk

Statistics

Installs: 72

Dependents: 0

Suggesters: 0

Stars: 0

1.0.0 2026-09-16 10:55 UTC

This package is auto-updated.

Last update: 2026-09-16 11:01:07 UTC


README

A typed PHP client for the AssetsPro API, with optional Laravel integration.

Use it to work with:

  • Assets
  • Uploads and downloads
  • Brands, categories, tags, and collections
  • Storage connections
  • Publications and exports
  • Members and invitations
  • API tokens
  • Share links

Requirements

  • PHP 8.3+
  • ext-curl
  • ext-json
  • Guzzle 7 or 8
  • ext-fileinfo for automatic MIME detection
  • Laravel 12 or 13 if using the Laravel integration

You will also need:

  • Your AssetsPro base URL
  • An API token
  • An organization ID for organization-scoped operations

Installation

composer require assets-pro/php-sdk

Basic Usage

Configure your credentials:

export ASSETSPRO_BASE_URL='https://assets.example.com'
export ASSETSPRO_TOKEN='your-api-token'
export ASSETSPRO_ORGANIZATION_ID='your-organization-id'

Create a client:

use AssetsPro\Client;

$client = new Client(
    baseUrl: getenv('ASSETSPRO_BASE_URL'),
    token: getenv('ASSETSPRO_TOKEN'),
    organizationId: getenv('ASSETSPRO_ORGANIZATION_ID'),
);

You can then access resources through the client:

$asset = $client->assets()->get($assetId);

$assets = $client->assets()->list();

$brands = $client->brands()->list();

$collections = $client->collections()->list();

Most API responses are returned as typed data objects.

Organization Scope

Most operations require an organization.

You can create an unscoped client to discover organizations:

$client = new Client($baseUrl, $token);

$organizations = $client->organizations()->list();

Then create an organization-scoped client:

$client = $client->forOrganization($organizationId);

forOrganization() returns a new client and leaves the original client unchanged.

Laravel

Laravel package discovery automatically registers the service provider and facade.

Add the following to your .env:

ASSETSPRO_BASE_URL=https://assets.example.com
ASSETSPRO_TOKEN=your-api-token
ASSETSPRO_ORGANIZATION_ID=your-organization-id

Publish the configuration if you need to customize it:

php artisan vendor:publish \
    --provider='AssetsPro\Laravel\AssetsProServiceProvider' \
    --tag=assetspro-config

Use dependency injection:

use AssetsPro\Client;

final class AssetController
{
    public function __construct(
        private readonly Client $assetsPro,
    ) {
    }
}

Or use the facade:

use AssetsPro\Laravel\AssetsPro;

$asset = AssetsPro::assets()->get($assetId);

Assets

List assets

use AssetsPro\Requests\AssetFilters;

$page = $client->assets()->list(
    new AssetFilters(
        q: 'campaign',
        perPage: 25,
    ),
);

foreach ($page as $asset) {
    echo $asset->name;
}

Filters are available for search, taxonomy, uploader, dates, dimensions, media type, status, sorting, and pagination.

Get an asset

$asset = $client->assets()->get($assetId);

Update an asset

use AssetsPro\Requests\AssetUpdate;

$asset = $client->assets()->update(
    $assetId,
    new AssetUpdate(
        name: 'Updated name',
        description: 'Updated description',
    ),
);

Optional fields are omitted unless supplied.

Explicit null, false, and empty arrays are preserved when supported by the API.

Archive, trash, and restore

$client->assets()->archive($assetId);

$client->assets()->trash($assetId);

$asset = $client->assets()->restore($assetId);

Uploads

The easiest way to upload a file is:

use AssetsPro\Requests\UploadFileOptions;

$upload = $client->upload(
    '/path/to/photo.jpg',
    new UploadFileOptions(
        name: 'Campaign photo',
        collectionIds: [$collectionId],
    ),
);

The SDK automatically:

  1. Initializes the upload
  2. Transfers the file directly to storage
  3. Completes the upload

To wait until processing finishes:

$upload = $client->upload(
    '/path/to/photo.jpg',
    wait: true,
);

Replace an existing asset

$upload = $client->upload(
    '/path/to/replacement.jpg',
    new UploadFileOptions(
        targetAssetId: $assetId,
    ),
);

Publish after processing

$upload = $client->upload(
    '/path/to/photo.jpg',
    new UploadFileOptions(
        publishAfterProcessing: true,
    ),
);

You can explicitly wait for processing or publication:

$ready = $client->uploads()->waitForProcessing($upload->id);

$published = $client->uploads()->waitForPublication($upload->id);

Uploads can also be inspected, retried, or cancelled through $client->uploads().

Downloads

Get a signed download URL

$url = $client->getDownloadUrl($assetId);

Signed URLs are temporary and should be generated when needed.

Stream a file

$stream = $client->download($assetId);

try {
    while (! $stream->eof()) {
        echo $stream->read(64 * 1024);
    }
} finally {
    $stream->close();
}

Download to disk

$bytesWritten = $client->downloadTo(
    $assetId,
    '/tmp/asset.jpg',
);

The destination file must not already exist.

Public URLs

Retrieve the currently available public URL:

$url = $client->getPublicUrl($assetId);

You can also retrieve both configured public URLs:

$urls = $client->getPublicUrls($assetId);

$customUrl = $urls->customUrl;
$defaultUrl = $urls->defaultUrl;

These methods report the asset's current publication state. They do not publish the asset automatically.

Pagination

Most list operations return Page<T>.

$page = $client->assets()->list(
    new AssetFilters(perPage: 25),
);

Access the current page:

foreach ($page as $asset) {
    echo $asset->name;
}

Fetch the next page:

$nextPage = $page->next();

Or iterate across multiple pages:

foreach ($page->iterate() as $asset) {
    echo $asset->name;
}

Pagination helpers retain the original filters.

Taxonomy

AssetsPro supports:

  • Brands
  • Brand roles
  • Categories
  • Tags
  • Collections

These resources use the same general pattern:

$categories = $client->categories()->list();

$category = $client->categories()->get($categoryId);

Creating and updating taxonomy records uses typed request objects.

use AssetsPro\Requests\TaxonomyCreate;

$category = $client->categories()->create(
    new TaxonomyCreate(
        name: 'Photography',
    ),
);

Collections

Collections can organize assets without changing their publication state.

Create or reuse a collection by name:

$resolved = $client->collections()->resolve('Campaign Assets');

$collection = $resolved->data;

Collections can also be archived, trashed, restored, and processed in bulk.

Operations involving large numbers of assets may continue asynchronously on the server.

Storage

AssetsPro supports:

  • Cloudflare R2
  • Amazon S3
  • S3-compatible storage

Create a storage connection:

use AssetsPro\Requests\StorageCreate;
use AssetsPro\Requests\StorageCredentials;

$connection = $client->storageConnections()->create(
    new StorageCreate(
        name: 'Private storage',
        provider: 'r2',
        region: 'auto',
        privateBucket: 'assets-private',
        usePathStyleEndpoint: true,
        credentials: new StorageCredentials(
            $accessKey,
            $secretKey,
        ),
        endpoint: $endpoint,
    ),
);

Verify and activate it:

$connection = $client->storageConnections()->verify($connection->id);

$connection = $client->storageConnections()->activate($connection->id);

Storage credentials are only required for storage administration.

Normal asset uploads and downloads do not expose storage credentials to the caller.

Publications

Publish an asset:

$publication = $client->publications()->publish($assetId);

Revoke publication:

$client->publications()->revoke($assetId);

Publication may continue processing after the initial request.

Use the public URL helpers to retrieve the currently available delivery URL.

Exports

Create a ZIP export:

$export = $client->exports()->create([
    $firstAssetId,
    $secondAssetId,
]);

Check its status:

$export = $client->exports()->get($export->id);

Download it when ready:

if ($export->status === 'ready') {
    $client->exports()->downloadTo(
        $export->id,
        '/tmp/assets.zip',
    );
}

Exports are generated asynchronously and expire after the server's configured retention period.

Members and Invitations

List organization members:

$members = $client->members()->list();

Update a role:

$member = $client->members()->update(
    $userId,
    'Editor',
);

Invite a user:

use AssetsPro\Requests\InvitationCreate;

$invitation = $client->invitations()->create(
    new InvitationCreate(
        email: 'user@example.com',
        role: 'Viewer',
    ),
);

Permission checks are enforced by the AssetsPro API.

API Tokens

Create an API token:

use AssetsPro\Requests\TokenCreate;

$result = $client->tokens()->create(
    new TokenCreate(
        name: 'Read-only integration',
        abilities: [
            'assets.view',
            'assets.download',
        ],
    ),
);

The plaintext token is returned only when it is created:

$token = $result->token;

Store it securely.

Tokens can also be listed, restricted by IP address, and revoked.

Share Links

Create a share link for an asset:

use AssetsPro\Requests\ShareCreate;

$share = $client->shareLinks()->create(
    new ShareCreate(
        name: 'Client review',
        assetId: $assetId,
        allowDownloads: false,
    ),
);

Share links can target either an asset or a collection.

They can optionally support:

  • Expiration
  • Password protection
  • Downloads

Existing share links can be listed, updated, or revoked.

Data Objects

API responses are represented by typed, read-only data objects.

Properties use camelCase:

$asset->createdAt;
$asset->activeRevision;
$asset->thumbnailUrl;

Convert an object back to the original API-style representation:

$data = $asset->toArray();

To distinguish between a missing field and an explicitly null field:

if ($asset->has('pending_revision')) {
    $pending = $asset->pendingRevision;
}

Errors

API failures throw ApiException.

Upload-specific failures throw UploadException.

use AssetsPro\Exceptions\ApiException;
use AssetsPro\Exceptions\UploadException;

try {
    $upload = $client->upload($path);
} catch (UploadException $e) {
    $uploadId = $e->uploadId;
    $phase = $e->phase;
} catch (ApiException $e) {
    $status = $e->status;
    $code = $e->errorCode;
    $errors = $e->errors;
    $requestId = $e->requestId;
}

Useful exception information can include:

  • HTTP status
  • Error code
  • Validation errors
  • Retry information
  • Request ID
  • Upload ID and failed upload phase

Sensitive credentials are redacted from exception messages and debug output.

Retries

The SDK automatically retries appropriate read operations and selected safe-to-repeat operations.

Mutating requests that may create or change resources are generally not retried automatically when the result could be ambiguous.

For uploads and similar operations, use the provided status and recovery methods rather than blindly repeating the original request.

Client Options

Customize behavior with Options:

use AssetsPro\Options;

$client = new Client(
    baseUrl: $baseUrl,
    token: $token,
    organizationId: $organizationId,
    options: new Options(
        timeoutSeconds: 30,
        connectTimeoutSeconds: 5,
        maxRetries: 2,
    ),
);

Available options include:

  • Request timeout
  • Connection timeout
  • Retry count
  • Maximum retry delay
  • Response size limits
  • Cancellation

The defaults are suitable for most applications.

Development

From the SDK package directory:

composer install
composer test
composer analyse
composer format
composer validate --strict

Run the complete verification suite with:

composer check

The package includes automated tests for resource operations, typed response handling, pagination, uploads, downloads, retries, error handling, and Laravel integration.

Project Structure

src/
├── Client.php
├── Resources/
├── Requests/
├── Data/
├── Exceptions/
└── Laravel/

tests/
examples/
config/

Most application code only needs to interact with:

  • Client
  • Resources
  • Requests
  • Data

The remaining classes support the SDK internally.

License

MIT LICENSE

Copyright © 2026 AssetsPro contributors.