Quickstart
The SDK is file-first: you start from a file and call operations on it. The upload, workflow creation, and waiting are handled for you — one chain, one result.
Compress an image
- TypeScript
- PHP
- Python
- Rust
import { gisl, OptimizeFor } from '@giveitsmaller/sdk';
const client = await gisl.create({ apiKey: 'REPLACE_ME_API_KEY' });
// Upload → compress → wait → resolve the download URL, in one chain.
const result = await client
.file('./photo.jpg')
.compress(OptimizeFor.Balanced)
.run({ maxWait: '5m' });
console.log('Compressed file:', result.url); // pre-signed download URL
<?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
Coming soon — the Python quickstart lands with its content ticket.
Coming soon — the Rust quickstart lands with its content ticket.
That is the full round trip. Worth knowing:
- Presets express intent.
OptimizeFor.Size,.Balanced, and.Qualitypick sensible options for the input's media type so you do not have to tune numbers. See Compress for per-call options. run()waits up to 10 minutes by default — override withmaxWait. For live progress instead of polling, subscribe to progress events.- Failures throw typed errors (
GislApiError,GislValidationError,GislTimeoutError, …). See Errors.
Many files at once
The same chain runs over a list — each file is uploaded once and fanned out:
- TypeScript
- PHP
- Python
- Rust
const many = await client
.files(['./a.jpg', './b.png'])
.compress(OptimizeFor.Balanced)
.run();
for (const artifact of many.artifacts) console.log(artifact.url);
$many = $client->files(['./a.jpg', './b.png'])
->compress(OptimizeFor::Balanced)
->run();
foreach ($many->artifacts as $artifact) {
echo $artifact->url, "\n";
}
Coming soon.
Coming soon.
Different recipes, one workflow — batch()
files() fans the same recipe across many inputs. When each input needs its
own recipe (different ops / options), pass a list of single-input keyed
recipes to batch([...]) — they run as one workflow and each result addresses
back by the key you gave that file (the second argument to file()):
- TypeScript
- PHP
- Python
- Rust
const hero = client.file('hero.jpg', 'hero').thumbnail({ width: 1200, height: 630 });
const avatar = client.file('avatar.jpg', 'avatar').thumbnail({ width: 256, height: 256 });
const result = await client.batch([hero, avatar]).run({ maxWait: '5m' });
console.log(result.byKey('hero').outputs[0].url);
console.log(result.byKey('avatar').outputs[0].url);
$hero = $client->file('hero.jpg', key: 'hero')->thumbnail(['width' => 1200, 'height' => 630]);
$avatar = $client->file('avatar.jpg', key: 'avatar')->thumbnail(['width' => 256, 'height' => 256]);
$result = $client->batch([$hero, $avatar])->run(maxWait: '5m');
echo $result->byKey('hero')->outputs[0]->url, "\n";
echo $result->byKey('avatar')->outputs[0]->url, "\n";
Coming soon.
Coming soon.
Each entry must be a single-input keyed recipe (file(input, 'key').<op>(…))
with a unique non-empty key — multi-input recipes (merge / archive /
overlay-watermark) are rejected with a GislConfigError before any upload. run()
only in v1 (no submit() yet), and no cross-recipe upload dedupe (two entries
sourcing the same file upload it twice). One failed entry lands in result.failed
without sinking the rest.
Where next
- Operations — compress, convert, thumbnail, merge, archive.
- Workflows — how jobs, sources, and outputs fit together.
- Errors — the error taxonomy and retry guidance.