Skip to main content

PHP

The giveitsmaller/sdk package is the official PHP client for GISL (Give It Smaller) — compress, convert, thumbnail, merge, and archive images, video, audio, and documents from PHP 8.1+.

Install​

The SDK targets the PSR-18 (HTTP client) and PSR-17 (HTTP factories) standards and resolves a concrete implementation through php-http/discovery. Install it alongside any PSR-18 client — Guzzle is the common choice:

composer require giveitsmaller/sdk guzzlehttp/guzzle http-interop/http-factory-guzzle

Requires PHP ^8.1. If you already have a PSR-18 client (e.g. Symfony HttpClient), inject it directly instead of installing Guzzle.

Published on Packagist

The composer require above is all you need — giveitsmaller/sdk and its transitive giveitsmaller/contracts dependency are on Packagist, with no repositories block or auth token required.

Authenticate​

Every request is authenticated with an API key sent as a Bearer token. Get a key from the dashboard at giveitsmaller.com. The SDK resolves the key from the first source that provides one: the explicit apiKey: argument, then GISL_API_KEY, then the [default] profile in ~/.gisl/credentials.

use Gisl\Sdk\Gisl;

// Explicit key:
$client = Gisl::create(apiKey: 'sk_live_...');

// Or rely on GISL_API_KEY / ~/.gisl/credentials:
$client = Gisl::create();

The credentials file is INI, one section per profile; pick another section with profile::

[default]
api_key = sk_live_...

With no key found, Gisl::create() throws GislMissingCredentialsError before any network call. Target a non-production environment with Gisl::create(apiKey: 'sk_...', environment: Environment::Staging).

The API host resolves in this order: baseUrl:, then environment:, then the GISL_BASE_URL and GISL_ENVIRONMENT environment variables, then production (https://api.giveitsmaller.com). A GISL_BASE_URL that is set but empty throws GislConfigError rather than falling back to production. See the Client reference for the progress-stream host.

baseUrl: does not move the progress stream. A client built with only baseUrl: has no stream host, so run() polls: its result's transport is RunTransport::Polling and the client raises one E_USER_WARNING (prefixed [GISL_STREAM_HOST_NOT_DECLARED]). Pass environment: or streamBaseUrl: as well to stream. See Seeing which transport a run used.

Quickstart​

The SDK is file-first: you start from a file (->file($path) for one, ->files([$paths]) for many) and call operations on it — upload, workflow creation, and waiting are handled for you in one chain.

<?php
require 'vendor/autoload.php';

use Gisl\Sdk\Gisl;
use Gisl\Sdk\Generated\SdkSpec\Enums\OptimizeFor;

$client = Gisl::create(apiKey: 'sk_...');

// Upload → compress → wait → resolve the download URL, in one chain.
$run = $client->file('./photo.jpg')
->compress(OptimizeFor::Balanced)
->run(maxWait: '5m');

echo $run->url; // pre-signed download URL

That is the full round trip. Worth knowing:

  • Presets express intent. OptimizeFor::Size, ::Balanced, and ::Quality pick sensible options for the input's media type. See Compress for per-call options.
  • run() waits up to 10 minutes by default — override with maxWait. For live progress instead of polling, subscribe to progress events.
  • Failures throw typed errors — see Errors.
Low-level escape hatch

File-first is the recommended path. When you need full control over the workflow payload, the low-level surface (uploadFile → createWorkflow → waitForWorkflow → getWorkflowDownloads) is available, with source factories from Gisl\Sdk\Sources.

Try it without an account​

Gisl::anonymous() builds a client with no credential at all — no API key, no environment variable, no profile, no cookie — for the guest flow:

use Gisl\Sdk\Gisl;

$client = Gisl::anonymous();

$run = $client->file('./photo.jpg')->compress()->run();
echo $run->url;

What a guest may do is decided by the API, not the SDK. Today that is:

  • any file type, up to 10,000,000 bytes per file (single-shot upload; multipart needs an account);
  • video at most 60 seconds long. The length is measured when the upload is probed; until then the API answers the create with probe_pending, and the SDK simply re-creates (backing off from 1 s to 30 s) until it is accepted, for up to 900 seconds, after which the API accepts a video whose length it could not measure (the SDK makes one last create about 2 s past that bound). A probeTimeoutMs ends that wait at its own end with GislProbePendingError: no create is scheduled past it, and a late timer may start one at most 1 s past. The run's maxWait (10 minutes by default) ends it with GislTimeoutError. maxWait starts before the upload, so to ride out the whole bound set it to at least 15 minutes plus your upload time;
  • the compress, convert and thumbnail operations;
  • 30 credits per IP per rolling 24 hours, priced like a signed-in workflow; a request that would cost more than is left is refused whole.

A larger file is refused locally, before anything is sent, with GislFeatureRequiresAuthError, as is any method that needs an account (credits, checkout and its status, cancel, resume, retry, listing workflows…). Everything else outside the rule comes back from the API as a GislApiError: a longer video with errorCode ANONYMOUS_LIMIT_EXCEEDED, another operation with ANONYMOUS_OPERATION_NOT_ALLOWED, and a spent allowance with ANONYMOUS_QUOTA_EXHAUSTED. The SDK carries the workflow's read token for you, so run() polls and downloads with nothing extra. Gisl::create() never falls back to guest mode: without a key it still throws GislMissingCredentialsError.

Where next​

  • Installation — every language, side by side.
  • Quickstart — the end-to-end walkthrough.
  • Operations — compress, convert, thumbnail, merge, archive.
  • Workflows — how jobs, sources, and outputs fit together.
  • Client reference — client options, bring-your-own HTTP client, and every low-level method.
  • Errors — the error taxonomy and retry guidance.