Skip to main content

Operations

Each job runs an ordered list of operations against its source. An operation has a type and a set of options.

The SDK's file-first chain exposes seven verbs:

OperationDoes
compressReduce file size for images, video, audio, and documents.
convertChange a file's format.
thumbnailGenerate a preview image.
mergeCombine several inputs into one output.
archiveBundle inputs into a ZIP or tarball.
watermarkStamp an image overlay or a text label onto an image.
splitFan one input into several outputs: PDF pages and GIF frames (stable), audio and video segments (beta).

Images also have output(), a single image-transform verb that keeps or changes the format and lowers to compress or convert for you.

A verb is not a contract OperationType

These seven are the SDK's vocabulary, not the wire's. A verb lowers to one or more contract operation types, and the contract's list is longer — it includes image_watermark, text_watermark, video_watermark, video_text_watermark, audio_to_video and passthrough, each with its own availability.

The mapping is not always one-to-one: watermark() routes to image_watermark or video_watermark depending on the base file's media type, and a chained call can lower to several jobs rather than several operations in one job.

You do not normally need the wire names — but if you are reading getSchema() (see reading the schema at runtime), an error payload, or the low-level operation(type, …) escape hatch, that is the vocabulary you will meet, and it will not match this table.

Accepted formats are per-operation, not global

Do not generalise from the first operation page you read. Each operation declares its own accepted MIME types, and they genuinely differ — merge accepts five audio types while compress and convert accept six, because merge does not take audio/mp4.

The per-operation lists on each page are correct for that page only. getSchema() returns the authoritative set at runtime, per operation and per media type, and is the thing to trust if you are deciding programmatically — read it like this, not by guessing its shape.

Options are media-type specific​

The valid option keys for an operation depend on the input's media type: a JPEG compress accepts different options than a video compress. The file-first chain knows each input's media type and validates the options before any upload — so a typo or an option that doesn't apply to the media type is caught locally rather than coming back as a server 422.

// Validated locally before the file is uploaded.
const result = await client
.compress('./photo.jpg', { quality: 80 })
.run({ maxWait: '5m' });

The authoritative option set​

The contracts are the source of truth for which options each media type accepts. To fetch the authoritative, per-MIME option list at runtime — for building a dynamic UI, or to confirm what the API currently supports — call getSchema() for the input's media type and operation.

Reading the schema at runtime​

If you only want to know whether an operation is available, call capabilities() first. It exists so that you do not have to handle getSchema()'s result shape: it fetches the schema and returns the capability matrix directly — a snapshot of every operation with no argument, or one operation's entry when you pass its type. It is on the client from gisl.create() / Gisl::create().

Reach for getSchema() when you need more than availability — the per-media-type option sets, for example. Its result is not the schema itself. It supports revalidation — pass a previous result's etag as ifNoneMatch — so it is either a hit carrying the schema or a not-modified answer carrying none:

  • TypeScript: { notModified: false, data, etag?, lastModified? } or { notModified: true, etag?, lastModified? }. The schema is under data.
  • PHP: a GetSchemaHitResult (the schema is $result->schema) or a GetSchemaNotModifiedResult. Narrow with instanceof.

The etag is the only validator the server honours. Both SDKs also accept an ifModifiedSince option, but the server ignores If-Modified-Since today, so it never produces a not-modified answer; lastModified is informational only.

Refuse, do not default

In plain JavaScript, schema.operations is undefined, not an error — the operations are at schema.data.operations. A caller that read the wrong path and fell back with ?? 'stable' treated every operation as callable, so the guard meant to skip an unavailable one never fired, and its tests stayed green.

Never default a missing entry to available. If your code needs a specific operation and the schema has no entry for it, refuse — as the example does — rather than falling back. Refuse a not-modified answer you did not ask for, too. An empty operations map is a valid response (a mimeType or operation filter can legitimately match nothing), so do not treat it as an error in itself; the missing-entry check is what catches it when it matters to you. An absent availability on an entry that is present means stable — the contract says so — but only default once you have proved the entry is there.

import { gisl } from '@giveitsmaller/sdk';

const client = await gisl.create({ apiKey: 'REPLACE_ME_API_KEY' });

// Availability only: no envelope to unwrap.
const splitCapability = await client.capabilities('split');
if (splitCapability === undefined) {
throw new Error('capabilities(): no entry for split');
}
console.log(splitCapability.availability ?? 'stable');

// The full schema: narrow on notModified, then hop through .data.
const schema = await client.getSchema();
if (schema.notModified) {
// No ifNoneMatch was sent, so there is no cached copy to reuse.
throw new Error('getSchema(): unexpected not-modified');
}
const operations = schema.data.operations;
const split = operations['split'];
if (split === undefined) {
throw new Error('getSchema(): no entry for split');
}
console.log(split.availability ?? 'stable');

capabilities() refuses nothing for you. It returns an empty snapshot (or undefined / null for one operation) when the server omits the capability matrix, or when a conditional header configured on the client turns the fetch into a not-modified answer. A missing entry there means "not known", never "available", so check it as the example does.

See the client reference for both methods' options.

Per-operation pages​

Planned: transform​

transform() — rotate by 0, 90, 180 or 270 degrees and flip none, horizontal, vertical or both — exists in both SDKs but is not yet available: every media type is planned, so workflow creation returns feature_not_available (422).