OptStuff

API Endpoint

Complete API endpoint reference — URL format, path and query parameters, authentication flow, and request/response details.

OptStuff exposes a single REST endpoint for image optimization. All transformations, authentication, and caching are encoded in the URL. For a step-by-step integration tutorial, see the Next.js Integration guide.

Endpoint Format

Requests are sent to your OptStuff deployment origin (for example, https://images.example.com). The format below shows only the path + query portion:

GET /api/v1/{projectSlug}/{operations}/{imageUrl}?key={publicKey}&sig={signature}&exp={expiresAt}
HEAD /api/v1/{projectSlug}/{operations}/{imageUrl}?key={publicKey}&sig={signature}&exp={expiresAt}

Path Parameters

ParameterDescriptionExample
projectSlugYour project identifiermy-blog
operationsImage operations (comma-separated), or _ for nonew_800,f_webp
imageUrlSource image URL (without protocol)cdn.example.com/photo.jpg

Query Parameters

ParameterRequiredDescription
keyYesPublic key (e.g., pk_abc123)
sigYesHMAC-SHA256 signature (see URL Signing)
expNoExpiration timestamp (Unix seconds)

Example Request

GET https://images.example.com/api/v1/my-blog/w_800,f_webp/images.example.com/photo.jpg?key=pk_abc123&sig=xyz789&exp=1706500000

Response

Vary defaults to Accept; if referer-domain validation is configured for the project, it becomes Accept, Referer.

Success (200) — GET

Returns the optimized image binary with long-lived caching headers:

HTTP/1.1 200 OK
Content-Type: image/webp
Cache-Control: public, s-maxage=31536000, max-age=31536000, immutable
Vary: Accept
X-Processing-Time: 42ms
X-Head-Fast-Path: 0
X-Original-Size-Sampled: 0
Server-Timing: auth;dur=7, transform;dur=35, total;dur=42
HeaderDescription
Content-TypeOutput format (image/webp, image/avif, image/png, image/jpeg)
Cache-Control1-year cache with immutable
VaryAccept and (when configured) Referer to preserve correct cache behavior
X-Processing-TimeServer-side processing time in milliseconds
X-Head-Fast-Path0 for normal image transform (GET), 1 for HEAD fast path
X-Original-Size-Sampled1 when an upstream HEAD probe is actually scheduled for this request, otherwise 0
Server-TimingRequest stage timing (auth, probe when applicable, transform, total) for performance debugging

Success (200) — HEAD

HEAD runs the same auth / signature / rate-limit checks, then performs a lightweight upstream availability probe before returning headers only (no image body):

HTTP/1.1 200 OK
Cache-Control: public, s-maxage=31536000, max-age=31536000, immutable
Vary: Accept
X-Processing-Time: 8ms
X-Head-Fast-Path: 1
Server-Timing: auth;dur=5, probe;dur=3, transform;dur=0, total;dur=8

Image optimization URLs are content-addressable: the URL encodes all parameters and a signature, so the same URL always produces the same output. This makes the 1-year cache duration safe — changing any parameter produces a different URL.

Errors

StatusCause
400Invalid path format, unsupported operation, or invalid operation value
401Missing/invalid/revoked/expired API key
403Invalid signature, forbidden referer, or blocked source domain
404Project not found, or upstream source returned 404 (passthrough)
410Upstream source returned 410 (passthrough)
429Rate limit exceeded
502Upstream fetch/transform failed (default for non-passthrough upstream errors)
500Internal processing failure, or upstream fetch/probe failure without a mappable status code (rare)

For upstream fetch/probe failures, the endpoint uses 502 as the primary failure status. Upstream 404 and 410 are passed through unchanged, and rare unmappable upstream/runtime failures return 500.

For HEAD, these error statuses are the same, but responses remain headers-only (no JSON body).

For the full error reference, see Error Codes.

Authentication Flow

When a request arrives, the server validates it in this order:

StepCheckFailure
1Parse key, sig, exp from query string401
2Look up API key; check not revoked/expired401
3Parse operations/image path and validate operation constraints400
4Verify HMAC-SHA256 signature (constant-time)403
5Find project by key's projectId; match slug404 / 401
6Check rate limits429
7Validate Referer header against project domains403
8Validate image source domain against project's domains403
9Route by method (GET transform / HEAD fast path probe)502 (primary upstream fetch/probe/transform failure), 404/410 passthrough, rare 500 fallback

Rate limiting is checked after signature verification so that invalid requests cannot exhaust quota.

Serverless Runtime Notes

This endpoint is optimized for serverless environments where cold starts matter:

  • Heavy modules (image engine and non-critical telemetry utilities) are lazy-loaded only when needed.
  • HEAD requests run the full auth/abuse checks, run a lightweight upstream probe, skip image transformation, and avoid loading transform dependencies.
  • Success-path usage tracking and request logging are scheduled with after() so the image response is returned first.
  • Project/API-key config changes normally propagate within cache TTL (~60s) unless explicit cache invalidation applies immediately.
  • If Redis for rate limiting is temporarily unavailable, requests are allowed (fail-open) so image delivery remains available.

These changes reduce initialization overhead for rejected requests and metadata-only probes while preserving the same API behavior.

Last updated on

On this page