Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Sdk Laravel Package

transloadit/php-sdk

Official PHP SDK for Transloadit, making it easy to integrate cloud file uploading and media processing into PHP apps. Build assemblies for image resizing, video encoding, and more, with signature verification and simple API helpers.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer and pull credentials from env — never hardcode the Auth Secret.

composer require transloadit/php-sdk
use Transloadit\Transloadit;

$transloadit = new Transloadit([
    'key'    => getenv('TRANSLOADIT_KEY'),    // public
    'secret' => getenv('TRANSLOADIT_SECRET'), // private, server-side only
]);

Start at the package's README and the two classes that matter: Transloadit\Transloadit (client, createAssembly()) and Transloadit\TransloaditResponse (wraps the decoded JSON body). The first real use case is a single-step image resize:

$response = $transloadit->createAssembly([
    'files' => ['/path/to/cat.jpg'],
    'params' => [
        'steps' => [
            'resized' => [
                'robot' => '/image/resize',
                'width' => 300,
                'height' => 300,
            ],
        ],
    ],
]);

if ($response->error) {
    throw new RuntimeException($response->error);
}

echo $response->data['assembly_id'];
$url = $response->results['resized'][0]['url']; // may be empty until assembly finishes

Treat $response->error as the failure branch, $response->data as the raw decoded payload, and $response->results / $response->uploads as convenience accessors into it. createAssembly() returns as soon as the assembly is created, not when it is done — see Gotchas.

If you only need to serve transformed assets through Transloadit's Smart CDN, you don't need an assembly at all — you need a signed URL. Since v3.3.0 the SDK no longer carries a Node-parity helper for that; use the official transloadit CLI (or your own HMAC) as described in the repo's parity workflow docs.

Implementation Patterns

Wrap the client in one container-bound service. The SDK is a thin curl wrapper with no PSR-18/PSR-17 support, so isolate it behind a small class (TransloaditService::resize(...)) that takes domain arguments and returns your own DTOs. This is what makes the rest of your app testable.

Template-first, params for overrides. For anything reused across the codebase, define the pipeline once in the Transloadit dashboard and pass template_id:

$transloadit->createAssembly([
    'files'  => $files,
    'params' => [
        'template_id' => config('services.transloadit.template_id'),
        // steps declared here override same-named template steps
        'steps' => ['resized' => ['width' => $width]],
    ],
]);

Pass arrays, not JSON strings, for params. The SDK serialises and signs the params; hand-encoding risks a signature mismatch or double encoding (see Gotchas).

Correlate with your own IDs via custom fields. Put order_id, user_id, or a job UUID in params['fields'] (or as your own metadata object) so webhook handlers can find the row without a fragile lookup table of assembly_ids.

Use notify_url + a webhook endpoint for completion. This is the sanctioned async pattern:

'params' => [
    'steps' => [...],
    'notify_url' => route('webhooks.transloadit'),
]

The handler should verify the signature over the raw request body, then look up your assembly row by assembly_id, download results, and mark the job done.

Send an auth.nonce when replay protection is enabled. As of v3.3.0 this is documented as an optional auth field on the params:

'params' => [
    'auth' => ['nonce' => (string) Str::uuid()],
    'steps' => [...],
]

Use a fresh, high-entropy value per request (a UUIDv4 or a random hex string of similar length), and persist it if you need to correlate or de-duplicate retries. Without it, accounts with replay protection turned on will reject repeats — including legitimate retries of the identical signed request.

Let the CLI own Smart CDN signatures. The SDK used to ship a hand-rolled Node-parity helper for Smart CDN URL signing; v3.3.0 replaces it with the official transloadit CLI and a documented parity workflow. In PHP practice this means: generate the signature with the CLI (or a shared HMAC routine you've verified against the CLI's output) and cache the resulting signed URL — don't re-derive it in a controller on every request.

Avoid uploading large files when you can. For user media already in S3/GCS or a public URL, use an import robot (/s3/import, /http/import) instead of shoving bytes through PHP's curl layer — it removes the memory ceiling and the risk of PHP timeouts killing the request mid-upload.

Reach for the lower-level request method for reads. createAssembly() is the happy path; for fetching an assembly by ID or hitting other endpoints, use the client's generic request method with url/method/params and let it handle signing. Keep those calls in your service wrapper, not in controllers.

Testing. Because the SDK instantiates its own curl transport, you cannot inject a mock transport. Test your service wrapper with a fake implementation, and cover the real client with a single integration test tagged @group integration that runs against a test template only when credentials exist. v3.3.0 adds a Docker-based harness and parity workflow you can crib from for a reproducible, credential-isolated run — and the system tests now randomize request signatures, which is the pattern to copy if your test account has replay protection on.

Gotchas and Tips

  • Assemblies are asynchronous. A successful createAssembly() call gives you an assembly_id and usually empty results. If you read $response->results[...][0]['url'] immediately you will get null/undefined-index errors intermittently — it works only when the pipeline is trivially fast. Either poll GET /assemblies/{id} with exponential backoff and a hard deadline, or rely on notify_url. Do not assume success means "done".
  • The SDK does not poll or retry for you. There is no built-in await/getAssembly helper like the Node SDK's. Budget for writing a small poller, and back off (e.g. 1s → 2s → 4s, cap at ~10s) rather than hammering the API.
  • No webhook verification helper. You must HMAC the raw body with your Auth Secret and compare (constant-time) against the signature Transloadit sends. Use file_get_contents('php://input') — not $request->all() re-encoded — because any whitespace change breaks the digest. Also verify over the exact bytes received; framework middleware that re-serialises JSON is a classic source of "signature always invalid".
  • Replay protection and auth.nonce. Newly documented in v3.3.0: if your account has replay protection enabled, two identical signed requests will be rejected. That bites any code that re-submits a stored params blob — queue retries, idempotency keys that reuse the payload, or a cached signed request. Add params['auth']['nonce'] with a fresh random value per attempt. Symptom looks like an auth failure but is a duplicate-request rejection; log the response body, not just the status.
  • Webhooks retry. Make the handler idempotent: record processed assembly_ids, return 2xx fast, and do heavy work (downloads, re-hosting) in a queue.
  • Result URLs are ephemeral. Transloadit's result URLs expire (hours, not weeks). Download and copy to your own storage in the completion handler; never store the URL as the canonical asset reference. Same applies to Smart CDN signed URLs — they carry an expiry, so cache them with a TTL well under it rather than persisting them.
  • Don't double-encode params. Passing an array is correct. If you pass an already-serialised string, the signature must be computed over those exact bytes — off-by-one quoting or key ordering yields INVALID_SIGNATURE, which looks like an auth failure but is a serialisation bug.
  • Error shapes are two-level. $response->error covers transport/HTTP failures; API-level errors arrive as a 200 with error/message inside $response->data. Check both. Log $response->data wholesale on failure — the API's error field names the offending step, which is what you actually need when debugging a robot config.
  • Large local uploads risk memory and time. The curl layer streams multipart, but PHP's max_execution_time and your reverse proxy's body limit still apply. Set explicit curl timeouts via the client config, and prefer import robots above ~50 MB.
  • Signing is a server-side operation. The key is safe to expose in browser-side "upload directly to Transloadit" flows, but the secret must never leave the backend. Keep the SDK out of any client bundle — and keep the transloadit CLI out of your web runtime too; treat it as a build/ops tool that produces signed assets, not something shelled out to per request.
  • Pin the package version and check release notes on upgrade. The library is small and stable, but the response-object property names are the de facto interface your code depends on (data, results, uploads, error) — a rename there is a silent break, not a type error, since these are dynamically populated. Assert their presence in your wrapper rather than spreading $response->results[...] access throughout the app. v3.3.0's removal of the bundled parity helper is exactly this class of change: it doesn't touch the response shape, but if you were calling it directly you now need the CLI path.
  • Don't assume the CLI is installed. If your signing routine depends on the transloadit CLI, gate it behind a health check or a startup assertion — a missing binary fails at the worst possible moment. Where you can, verify your own HMAC implementation against the CLI once in CI and then use the pure-PHP path in production.
  • Extension point: when you need custom behaviour (signed uploads, presigned URLs, region selection), the client accepts overrides at construction — check the source's $config handling before assuming a property exists, since the config surface is under-documented compared with the REST API.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings