Documentation

Learn how to transform images with simple URL parameters. Our pipeline-based system processes transformations in the order you specify.

Quick Start

Get started in minutes

Transform your first image in 4 simple steps.
1
Create Account

Sign up at xform.media to get started with your free trial.

2
Create Source

Connect your S3 bucket, Cloudflare R2 storage, or any public URL as an image source.

3
Get Subdomain

Your images are served from {subdomain}.xform.media

4
Start Transforming

Add query parameters to any image URL to transform on the fly.

Your first transformation

Resize to 800x600, crop to cover, convert to WebP at 85% quality:

https://my-images.xform.media/photos/hero.jpg?w=800&h=600&fit=cover&f=webp&q=85
Core Concept

Pipeline-based transformations

Understanding how parameters are processed is key to getting the results you want.

xform processes query parameters in the order they appear in the URL, like a pipeline. Each transformation is applied sequentially, allowing you to chain operations in a predictable way.

Parameter Grouping

Some related parameters are automatically grouped together into single operations:

  • Resize parameters (w, h, fit, p) are combined into one resize operation
  • Modulate parameters (brightness, saturation, hue) are combined into one color adjustment

When a non-grouped parameter is encountered, any pending grouped operations are executed first.

Interactive Pipeline Demo

Click parameters to add them to the URL. Watch how they get grouped and ordered in the pipeline.

Available Parameters
Pipeline Execution Order
Add parameters above to see how they're processed
Legend
Resize (grouped)
Modulate (grouped)
Blur/Sharpen
Rotate/Flip
Format/Quality

Example: Multi-step pipeline

https://my-images.xform.media/image.jpg?w=800&blur=3&rotate=90&grayscale=true&f=webp

Execution order:

  1. Resize to 800px wide
  2. Apply blur (sigma=3)
  3. Rotate 90 degrees
  4. Convert to grayscale
  5. Output as WebP

Example: Extract then transform

https://my-images.xform.media/image.jpg?e=100,200,400,300&w=200&blur=2

Execution order:

  1. Extract 400x300 region starting at (100,200)
  2. Resize to 200px wide
  3. Apply blur
API Reference

Transformation parameters

Complete reference for all available query parameters.

Resize & Crop

ParameterAliasExampleDescription
widthww=400Width in pixels (1-8192)
heighthh=300Height in pixels (1-8192)
fit-fit=covercover, contain, fill, inside, outside
positionpp=top-leftCrop anchor point
extractee=10,20,300,400Pixel-precise crop (left,top,width,height)

Rotation & Flip

ParameterAliasExampleDescription
rotaterr=90Rotate 0, 90, 180, or 270 degrees
flip-flip=trueMirror vertically
flop-flop=trueMirror horizontally

Effects & Filters

ParameterAliasExampleDescription
blurbb=5Gaussian blur (sigma 0.3-1000)
sharpenss=trueSharpen image
brightness-brightness=1.2Brightness multiplier (1.0 = no change)
saturation-saturation=1.5Saturation multiplier (1.0 = no change)
hue-hue=45Hue shift (0-360 degrees)
grayscale-grayscale=trueConvert to grayscale

Format & Quality

ParameterAliasExampleDescription
formatff=webpjpeg, png, webp, avif, gif, tiff
qualityqq=80Compression quality (1-100, default: 80)

Metadata Extraction

ParameterAliasExampleDescription
metadata-?metadataReturns image dimensions, format, channels
colors-?colorsReturns dominant + vibrant color palette
base64-?base64Returns base64-encoded thumbnail (LQIP)
exif-?exifReturns camera/GPS EXIF data (if enabled)
meta-?meta=trueReturns all metadata combined
Reference

Position values

Control where the image is anchored during cropping with the position parameter.

Basic Positions

toprightbottomleftcenter

Corner Positions

top-lefttop-rightbottom-leftbottom-right

Cardinal Positions

northsoutheastwestnortheastnorthwestsoutheastsouthwest

Smart Positioning

entropy

Focus on the busiest area of the image (high detail regions).

attention

Focus on prominent features like faces or objects.

Note: You can use hyphens or underscores interchangeably. For example, p=top-left and p=top_left are equivalent.

Reference

Fit values

Control how images are resized to fit within the specified dimensions.
cover

Fill dimensions, crop excess (default)

contain

Fit within dimensions, may letterbox

fill

Stretch to fill (distorts aspect ratio)

inside

Resize to fit inside dimensions

outside

Resize to cover dimensions minimum

Social Sharing

OG Image Generation

Generate beautiful Open Graph images for social media sharing on the fly.

xform can automatically generate Open Graph (OG) images for your content. These images appear when your links are shared on social media platforms like Twitter, Facebook, LinkedIn, and Slack.

OG images are generated using your source image as the background, with customizable overlays for logos, titles, and descriptions. All styling is configured in the admin dashboard.

Dynamic Backgrounds

Use any image from your source as the background, or upload a custom background image.

Custom Text Overlays

Add titles and descriptions with customizable fonts, colors, and positioning.

Brand Consistency

Add your logo and apply consistent styling across all generated OG images.

Setup

Configuring OG Images

Configure your OG image settings in the admin dashboard.

Background Options

Source Image

Uses the requested image as the background (default behavior).

Custom Background

Upload a static background image to use for all OG images.

Solid Color

Use a solid background color instead of an image.

Mask Overlay

Apply a semi-transparent overlay to improve text readability over complex backgrounds.

ColorOpacity

Logo Settings

  • Upload logo - PNG or SVG with transparency recommended
  • Position - Top-left, top-right, bottom-left, bottom-right
  • Size - Width and height in pixels

Text Styling

  • Font family - Choose from system fonts
  • Font size - Title and description sizes
  • Text color - Customize for readability
  • Position - X/Y coordinates for precise placement

Border

Optionally add a colored border around the OG image for brand recognition.

Implementation

Using OG Images

Generate OG images by adding query parameters to your image URLs.

OG Image Parameters

ParameterAliasExampleDescription
type-type=ogEnables OG image generation mode
title-title=My%20TitleMain title text (URL-encoded)
description-description=My%20descDescription text (URL-encoded)
formatff=pngOutput format: png, jpeg, or webp (default: png)

Basic Example

Generate an OG image with title and description:

https://my-images.xform.media/photos/hero.jpg?type=og&title=Welcome%20to%20Our%20Site&description=Discover%20amazing%20content

Without Source Image

Use the /og endpoint to generate OG images without specifying a source image. Uses your configured default background.

https://my-images.xform.media/og?title=My%20Title&description=My%20description

Output Formats

OG images default to PNG for best quality, but you can specify other formats.

https://my-images.xform.media/image.jpg?type=og&title=Hello&f=webp

HTML Meta Tags

Add these meta tags to your HTML to enable social sharing previews:

<meta property="og:image" content="https://{domain}/image.jpg?type=og&title=..." />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="https://{domain}/image.jpg?type=og&title=..." />

Tip: OG images are generated at 1200x630 pixels by default, which is the recommended size for most social platforms.

Video Streaming

Adaptive video streaming

Ingest video from your source, transcode to HLS adaptive bitrate, and stream via an embeddable player.

xform handles the entire video pipeline: ingest from your existing source (S3, R2, or any supported provider), transcode into multiple quality levels using FFmpeg, and serve via HLS with an embeddable player. Your source files are never modified - xform stores all transcoded output on its own infrastructure.

1080p
Max quality
HLS
Adaptive bitrate
MP4
Direct download
VTT
Captions + search

How it works

1
Ingest

Ingest a video from your source, or upload directly to xform via the SDK.

2
Transcode

xform transcodes to HLS (1080p/720p/480p) + MP4 + thumbnail automatically.

3
Stream

Embed the player or use HLS URLs directly. Webhooks notify you when ready.

Setup

SDK installation

Install the xform SDK and configure the client for video operations.

Install

npm install @xformmedia/sdk

Configure the client

import { XformClient } from '@xformmedia/sdk'

const client = new XformClient({
  sourceId: 'src_...',
  organizationId: 'org_...',
  apiKey: 'xfm_...',
  baseUrl: 'https://admin.xform.media',
  streamBaseUrl: 'https://acme.xform.media'
})

Note: The streamBaseUrl is your source's subdomain URL. It's required for generating embed codes and streaming URLs.

Upload

Ingest and transcode

There are two ways to get video into xform: ingest a file that already exists in your source, or upload directly to xform's infrastructure via a presigned URL.
Option A: Ingest from your source

The video already lives in your S3, R2, or other configured source. Tell xform the file key and it pulls the video for transcoding. Your source file is never modified.

Option B: Upload to xform

Don't need the source file in your own storage? Upload directly to xform's infrastructure via a presigned URL. Useful for user-generated content or when you just want the streaming output.

Option A: Ingest from your source

// Ingest a video that already exists in your source
const result = await client.ingest({
  key: 'recordings/standup.mp4',
  callbackUrl: 'https://example.com/webhook'
})

console.log(result.videoKey)
// → "recordings-standup"

console.log(result.transcodeStatus)
// → "pending"

Option B: Upload to xform, then ingest

// Get a presigned URL (uploads to xform, not your source)
const { uploadUrl, key } = await client.createUploadUrl({
  filename: 'intro.mp4',
  contentType: 'video/mp4'
})

// Upload directly from the browser to xform
await fetch(uploadUrl, {
  method: 'PUT',
  body: videoFile,
  headers: { 'Content-Type': 'video/mp4' }
})

// Then trigger transcoding
const result = await client.ingest({ key })

Transcoding details

QualityBitrateCodecNotes
1080p4 MbpsH.264Only if source is 1080p+
720p2 MbpsH.264Only if source is 720p+
480p800 kbpsH.264Minimum rendition

Real-time status events

// Listen for transcode status changes via SSE
const stream = client.events()

stream.on('video.ready', (video) => {
  console.log('Stream URL:', video.streamUrl)
  console.log('Duration:', video.duration, 'seconds')
})

stream.on('video.failed', (video) => {
  console.error('Transcode failed:', video.errorMessage)
})

// Clean up when done
stream.close()
Playback

Embed player

Embed a fully-featured video player with a single line of code.

Generate embed code

const iframe = client.embed('intro', {
  autoplay: false,
  muted: false,
  controls: true,
  quality: 'auto',
  captions: true,
  search: true,
  color: '6366f1',
  title: 'Product Introduction'
})

Or use the URL directly

https://acme.xform.media/_embed/intro
  ?autoplay=1
  &muted=1
  &quality=720p
  &captions=1
  &color=6366f1

Embed options

autoplay

Start playing automatically (requires muted on most browsers).

quality

Initial quality: auto, 1080p, 720p, or 480p.

captions

Show captions by default (if VTT file is available).

search

Enable fuzzy caption search within the player.

t

Start playback at a specific time in seconds.

color

Accent color for the player controls (hex without #).

Player features

Adaptive bitrate
Speed controls (0.5x-2x)
Captions + search
Share with timestamp
Fullscreen
Keyboard shortcuts
Quality selector
Auto poster/thumbnail
Events

Webhooks

Receive real-time notifications when video transcoding completes or fails.

Webhook events

video.ready

Transcoding completed. Includes stream URL, duration, dimensions, and thumbnail URL.

video.failed

Transcoding failed after all retry attempts. Includes error message.

video.renamed

Video display name was changed.

Signature verification: All webhooks include an X-Webhook-Signature header containing an HMAC-SHA256 signature for payload verification.

Example payload

{
  "event": "video.ready",
  "sourceId": "src_...",
  "videoKey": "intro",
  "timestamp": "2026-03-16T10:30:00Z",
  "data": {
    "streamUrl": "/_v/intro.m3u8",
    "downloadUrl": "/_v/intro.mp4",
    "thumbnailUrl": "/_v/intro/thumbnail.jpg",
    "duration": 124.5,
    "width": 1920,
    "height": 1080
  }
}

Delivery

  • 3 retry attempts with exponential backoff
  • Per-video callback URL (set on ingest)
  • Source-level webhook (configured in admin)
Insights

Video analytics

Built-in analytics for every video - no third-party scripts required.

Tracked metrics

Views and sessions

Total views, unique sessions, views by day.

Engagement

Average watch duration, completion rate, play/pause/ended events.

Quality

Quality distribution across viewers, quality change events.

Referrers

Top referring domains and pages.

Query analytics via SDK

// Summary analytics
const summary = await client.videos.analytics()
console.log(summary.totalViews)
console.log(summary.avgCompletionRate)

// Detailed breakdown for a specific video
const detailed = await client.videos.analytics({
  videoKey: 'intro',
  detailed: true,
  since: '2026-03-01',
  until: '2026-03-16'
})

Video management

// List all videos
const { data } = await client.videos.list()

// Get a specific video
const video = await client.videos.get('intro')

// Upload captions
await client.videos.uploadCaptions(
  'intro',
  'WEBVTT\n\n00:00.000 --> 00:05.000\nHello!'
)

// Delete a video
await client.videos.delete(video.id)
Integration

Source configuration

Configure your image sources for optimal performance.

Supported Storage Providers

Amazon S3

Standard S3 buckets with IAM credentials.

Cloudflare R2

S3-compatible storage with zero egress fees.

Public URL

Any publicly accessible web URL as an image source.

Required Credentials

  • Bucket name - Your storage bucket identifier
  • Region - AWS region or R2 account ID
  • Access Key ID - IAM or R2 API token
  • Secret Access Key - Associated secret

Security tip: Only provide credentials with read-only permissions. xform only needs to read your images, never write or delete.

Your Access Key ID and Secret Access Key are encrypted at rest and never exposed in logs or API responses.

Optional Settings

  • Cache settings - Configure max-age and s-maxage for CDN
  • EXIF extraction - Enable/disable EXIF metadata extraction
Integration

Custom domains

Serve transformed images from your own subdomain instead of the default xform.media domain.

Instead of serving images from {subdomain}.xform.media, you can use your own subdomain like cdn.example.com or media.example.com.

Important: Only subdomains are supported (e.g., cdn.example.com). Apex/root domains (e.g., example.com) are not supported.

Setup Steps

1
Add a CNAME record

Point your subdomain to xform.media in your DNS provider.

cdn.example.com  CNAME  xform.media
2
Add a TXT record

Add the TXT record shown in the admin dashboard to prove domain ownership.

_cf-custom-hostname.cdn.example.com  TXT  <verification-token>
3
Activate in admin

Enter your subdomain in the source settings. SSL is provisioned automatically once DNS records are verified.

Example

Once configured, your images are served from your custom subdomain:

Serve transformed images from your own domain:

https://cdn.example.com/photos/hero.jpg?w=800&f=webp

Apex domains not supported: You must use a subdomain (e.g., cdn.example.com), not a root domain (e.g., example.com). This is because CNAME records cannot be set on apex domains with most DNS providers.

DNS propagation: It may take a few minutes for DNS changes to propagate. The admin dashboard will show the verification status in real time.

Performance

Caching

Transformed images are cached at the edge for fast delivery.

xform automatically caches transformed images using CDN edge caching. Cache headers are configured per-source:

Cache-Control: public, max-age=31536000, s-maxage=31536000

max-age

Browser cache duration. Configure this based on how often your images change.

s-maxage

CDN cache duration. Set this higher for longer edge caching.

Responses

Response types

xform returns either transformed images or JSON metadata.

Image Response (default)

When you request a transformation without metadata parameters, xform returns the transformed image with the appropriate Content-Type header.

Returns a WebP image:

https://my-images.xform.media/photo.jpg?w=400&f=webp

JSON Metadata Response

When you include metadata parameters, xform returns a JSON response with the requested data.

Returns JSON with dimensions and color palette:

https://my-images.xform.media/photo.jpg?metadata&colors

Example JSON Response

{
  "metadata": {
    "width": 1920,
    "height": 1080,
    "format": "jpeg",
    "channels": 3,
    "hasAlpha": false
  },
  "colors": {
    "dominant": { "rgb": [64, 128, 192], "hex": "#4080c0" },
    "vibrant": { "rgb": [48, 160, 255], "hex": "#30a0ff" },
    "palette": [...]
  }
}
Troubleshooting

Error handling

Common HTTP status codes and their meanings.
Status CodeMeaning
400Invalid parameters - check your query string
403Source suspended - contact support
404Image not found at the specified path
500Processing error - try again or contact support
Limits

Technical constraints

Maximum values and limits for transformation parameters.
8192px
Max dimension
1-100
Quality range
0.3-1000
Blur sigma
90/180/270
Rotation degrees

Supported Output Formats

jpegjpgpngwebpavifgiftiff
Menu