openapi: 3.0.3
info:
title: Truss Image Server API
version: 0.24.0
description: |
HTTP API for the Truss image toolkit.
Successful transform requests return image bytes directly as `image/*` or
`image/svg+xml`; they do not return JSON envelopes. Failures are reported as
RFC 9457 `application/problem+json`, with a `type` URI naming the class of
failure; the classes are listed in `docs/problems.md`.
Choose an endpoint based on how the source image is supplied:
- `GET /images/by-path`: public, cache-friendly delivery for files under the
configured storage root.
- `GET /images/by-url`: public, cache-friendly delivery for remote HTTP(S)
sources.
- `POST /images:transform`: private server-to-server transforms using a JSON body.
- `POST /images`: private uploads using `multipart/form-data`.
Common transform options are shared across endpoints. When `format` is omitted,
the server reads `Accept` and picks the format it prefers among the ones the header
names, and keeps the input format when the header names none. An `Accept` of `*/*`
names none: RFC 9110 section 12.5.1 makes it the same request as a missing `Accept`,
so both keep the input format rather than transcoding.
The two private endpoints take their options from the request body and read no query
parameters. A query string on either is rejected with `400 Bad Request`.
**Watermark compositing** is available on all transform endpoints. Public GET
endpoints accept `watermarkUrl`, `watermarkPosition`, `watermarkOpacity`, and
`watermarkMargin` query parameters. The JSON endpoint accepts a `watermark`
object. The multipart endpoint accepts `watermark`, `watermark_position`,
`watermark_opacity`, and `watermark_margin` form fields.
license:
name: MIT
url: https://opensource.org/licenses/MIT
servers:
- url: http://localhost:8080
description: Local development
tags:
- name: Transform
description: Endpoints that fetch or accept an image, apply transform options, and return transformed bytes.
- name: Health
description: Lightweight probes for liveness and readiness checks.
- name: Observability
description: Operator-facing metrics and runtime diagnostics.
paths:
/images/by-path:
get:
tags: [Transform]
summary: Transform an image by storage path
description: |
Public, cache-friendly transform endpoint for files identified by path.
Also supports `HEAD` requests, which return the same headers without a body.
When the storage backend is `filesystem` (default), the `path` query
parameter is resolved relative to `TRUSS_STORAGE_ROOT`; path traversal
and out-of-root access are rejected. When the backend is `s3`, `gcs`,
or `azure`, the path is used as the object key (leading `/` is stripped
automatically).
This endpoint requires signed URL authentication through `keyId`,
`expires`, and `signature`.
Output selection rules:
- When `format` is present, that format is requested explicitly and the
`Accept` header is ignored.
- When `format` is omitted, the server tries `Accept` negotiation and
otherwise keeps the input format.
- When both `width` and `height` are present without `fit`, `contain`
is applied.
operationId: transformImageByPath
security:
- SignedUrlAuth: []
parameters:
- $ref: '#/components/parameters/SourcePath'
- $ref: '#/components/parameters/SourceVersion'
- $ref: '#/components/parameters/KeyId'
- $ref: '#/components/parameters/Expires'
- $ref: '#/components/parameters/Signature'
- $ref: '#/components/parameters/Width'
- $ref: '#/components/parameters/Height'
- $ref: '#/components/parameters/Fit'
- $ref: '#/components/parameters/Position'
- $ref: '#/components/parameters/Format'
- $ref: '#/components/parameters/Quality'
- $ref: '#/components/parameters/Optimize'
- $ref: '#/components/parameters/TargetQuality'
- $ref: '#/components/parameters/Background'
- $ref: '#/components/parameters/Rotate'
- $ref: '#/components/parameters/AutoOrient'
- $ref: '#/components/parameters/StripMetadata'
- $ref: '#/components/parameters/PreserveExif'
- $ref: '#/components/parameters/Crop'
- $ref: '#/components/parameters/Blur'
- $ref: '#/components/parameters/Sharpen'
- $ref: '#/components/parameters/Grayscale'
- $ref: '#/components/parameters/WithoutEnlargement'
- $ref: '#/components/parameters/WatermarkUrl'
- $ref: '#/components/parameters/WatermarkPosition'
- $ref: '#/components/parameters/WatermarkOpacity'
- $ref: '#/components/parameters/WatermarkMargin'
- $ref: '#/components/parameters/Preset'
responses:
'200':
$ref: '#/components/responses/ImageBinary'
'304':
$ref: '#/components/responses/NotModified'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'406':
$ref: '#/components/responses/NotAcceptable'
'413':
$ref: '#/components/responses/PayloadTooLarge'
'415':
$ref: '#/components/responses/UnsupportedMediaType'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'500':
$ref: '#/components/responses/InternalError'
'501':
$ref: '#/components/responses/NotImplemented'
'502':
$ref: '#/components/responses/BadGateway'
'503':
$ref: '#/components/responses/ServiceUnavailable'
'508':
$ref: '#/components/responses/LoopDetected'
'429':
$ref: '#/components/responses/TooManyRequests'
head:
tags: [Transform]
summary: Inspect transformed image headers by storage path
description: |
Same contract as `GET /images/by-path`, but returns headers only and no body.
operationId: headTransformImageByPath
security:
- SignedUrlAuth: []
parameters:
- $ref: '#/components/parameters/SourcePath'
- $ref: '#/components/parameters/SourceVersion'
- $ref: '#/components/parameters/KeyId'
- $ref: '#/components/parameters/Expires'
- $ref: '#/components/parameters/Signature'
- $ref: '#/components/parameters/Width'
- $ref: '#/components/parameters/Height'
- $ref: '#/components/parameters/Fit'
- $ref: '#/components/parameters/Position'
- $ref: '#/components/parameters/Format'
- $ref: '#/components/parameters/Quality'
- $ref: '#/components/parameters/Optimize'
- $ref: '#/components/parameters/TargetQuality'
- $ref: '#/components/parameters/Background'
- $ref: '#/components/parameters/Rotate'
- $ref: '#/components/parameters/AutoOrient'
- $ref: '#/components/parameters/StripMetadata'
- $ref: '#/components/parameters/PreserveExif'
- $ref: '#/components/parameters/Crop'
- $ref: '#/components/parameters/Blur'
- $ref: '#/components/parameters/Sharpen'
- $ref: '#/components/parameters/Grayscale'
- $ref: '#/components/parameters/WithoutEnlargement'
- $ref: '#/components/parameters/WatermarkUrl'
- $ref: '#/components/parameters/WatermarkPosition'
- $ref: '#/components/parameters/WatermarkOpacity'
- $ref: '#/components/parameters/WatermarkMargin'
- $ref: '#/components/parameters/Preset'
responses:
'200':
$ref: '#/components/responses/ImageBinary'
'304':
$ref: '#/components/responses/NotModified'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'406':
$ref: '#/components/responses/NotAcceptable'
'413':
$ref: '#/components/responses/PayloadTooLarge'
'415':
$ref: '#/components/responses/UnsupportedMediaType'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'500':
$ref: '#/components/responses/InternalError'
'501':
$ref: '#/components/responses/NotImplemented'
'502':
$ref: '#/components/responses/BadGateway'
'503':
$ref: '#/components/responses/ServiceUnavailable'
'508':
$ref: '#/components/responses/LoopDetected'
'429':
$ref: '#/components/responses/TooManyRequests'
/images/by-url:
get:
tags: [Transform]
summary: Transform an image from a remote URL
description: |
Public, cache-friendly transform endpoint for remote HTTP(S) sources.
Also supports `HEAD` requests, which return the same headers without a body.
Use this when the source image is hosted elsewhere and should be fetched by
Truss on demand. Remote fetches are subject to URL validation, redirect
limits, and source size limits.
This endpoint requires signed URL authentication through `keyId`,
`expires`, and `signature`.
Output selection rules:
- When `format` is present, that format is requested explicitly and the
`Accept` header is ignored.
- When `format` is omitted, the server tries `Accept` negotiation and
otherwise keeps the input format.
- When both `width` and `height` are present without `fit`, `contain`
is applied.
operationId: transformImageByUrl
security:
- SignedUrlAuth: []
parameters:
- $ref: '#/components/parameters/SourceUrl'
- $ref: '#/components/parameters/SourceVersion'
- $ref: '#/components/parameters/KeyId'
- $ref: '#/components/parameters/Expires'
- $ref: '#/components/parameters/Signature'
- $ref: '#/components/parameters/Width'
- $ref: '#/components/parameters/Height'
- $ref: '#/components/parameters/Fit'
- $ref: '#/components/parameters/Position'
- $ref: '#/components/parameters/Format'
- $ref: '#/components/parameters/Quality'
- $ref: '#/components/parameters/Optimize'
- $ref: '#/components/parameters/TargetQuality'
- $ref: '#/components/parameters/Background'
- $ref: '#/components/parameters/Rotate'
- $ref: '#/components/parameters/AutoOrient'
- $ref: '#/components/parameters/StripMetadata'
- $ref: '#/components/parameters/PreserveExif'
- $ref: '#/components/parameters/Crop'
- $ref: '#/components/parameters/Blur'
- $ref: '#/components/parameters/Sharpen'
- $ref: '#/components/parameters/Grayscale'
- $ref: '#/components/parameters/WithoutEnlargement'
- $ref: '#/components/parameters/WatermarkUrl'
- $ref: '#/components/parameters/WatermarkPosition'
- $ref: '#/components/parameters/WatermarkOpacity'
- $ref: '#/components/parameters/WatermarkMargin'
- $ref: '#/components/parameters/Preset'
responses:
'200':
$ref: '#/components/responses/ImageBinary'
'304':
$ref: '#/components/responses/NotModified'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'406':
$ref: '#/components/responses/NotAcceptable'
'413':
$ref: '#/components/responses/PayloadTooLarge'
'415':
$ref: '#/components/responses/UnsupportedMediaType'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'500':
$ref: '#/components/responses/InternalError'
'501':
$ref: '#/components/responses/NotImplemented'
'502':
$ref: '#/components/responses/BadGateway'
'503':
$ref: '#/components/responses/ServiceUnavailable'
'508':
$ref: '#/components/responses/LoopDetected'
'429':
$ref: '#/components/responses/TooManyRequests'
head:
tags: [Transform]
summary: Inspect transformed image headers by remote URL
description: |
Same contract as `GET /images/by-url`, but returns headers only and no body.
operationId: headTransformImageByUrl
security:
- SignedUrlAuth: []
parameters:
- $ref: '#/components/parameters/SourceUrl'
- $ref: '#/components/parameters/SourceVersion'
- $ref: '#/components/parameters/KeyId'
- $ref: '#/components/parameters/Expires'
- $ref: '#/components/parameters/Signature'
- $ref: '#/components/parameters/Width'
- $ref: '#/components/parameters/Height'
- $ref: '#/components/parameters/Fit'
- $ref: '#/components/parameters/Position'
- $ref: '#/components/parameters/Format'
- $ref: '#/components/parameters/Quality'
- $ref: '#/components/parameters/Optimize'
- $ref: '#/components/parameters/TargetQuality'
- $ref: '#/components/parameters/Background'
- $ref: '#/components/parameters/Rotate'
- $ref: '#/components/parameters/AutoOrient'
- $ref: '#/components/parameters/StripMetadata'
- $ref: '#/components/parameters/PreserveExif'
- $ref: '#/components/parameters/Crop'
- $ref: '#/components/parameters/Blur'
- $ref: '#/components/parameters/Sharpen'
- $ref: '#/components/parameters/Grayscale'
- $ref: '#/components/parameters/WithoutEnlargement'
- $ref: '#/components/parameters/WatermarkUrl'
- $ref: '#/components/parameters/WatermarkPosition'
- $ref: '#/components/parameters/WatermarkOpacity'
- $ref: '#/components/parameters/WatermarkMargin'
- $ref: '#/components/parameters/Preset'
responses:
'200':
$ref: '#/components/responses/ImageBinary'
'304':
$ref: '#/components/responses/NotModified'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'406':
$ref: '#/components/responses/NotAcceptable'
'413':
$ref: '#/components/responses/PayloadTooLarge'
'415':
$ref: '#/components/responses/UnsupportedMediaType'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'500':
$ref: '#/components/responses/InternalError'
'501':
$ref: '#/components/responses/NotImplemented'
'502':
$ref: '#/components/responses/BadGateway'
'503':
$ref: '#/components/responses/ServiceUnavailable'
'508':
$ref: '#/components/responses/LoopDetected'
'429':
$ref: '#/components/responses/TooManyRequests'
/images:transform:
post:
tags: [Transform]
summary: Transform an image by reference
description: |
Private server-to-server transform endpoint.
The request body identifies the source image as a storage path, a remote
URL, or an object-storage reference (bucket + key) and provides an
optional `options` object. This is the
most convenient endpoint for backend callers that want to authenticate with a
Bearer token instead of generating signed public URLs.
When `options.format` is omitted, the server tries `Accept` negotiation and
otherwise keeps the input format. An `Accept` of `*/*` states no preference and
keeps the input format.
This operation reads no query parameters. A request that carries a query string
is rejected with `400 Bad Request` naming the parameters it carried.
operationId: transformImageByReference
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TransformImageRequest'
example:
source:
kind: path
path: /photos/hero.jpg
version: v3
options:
width: 1600
format: webp
quality: 82
optimize: auto
targetQuality: ssim:0.98
autoOrient: true
stripMetadata: true
responses:
'200':
$ref: '#/components/responses/ImageBinary'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'406':
$ref: '#/components/responses/NotAcceptable'
'413':
$ref: '#/components/responses/PayloadTooLarge'
'415':
$ref: '#/components/responses/UnsupportedMediaType'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'500':
$ref: '#/components/responses/InternalError'
'501':
$ref: '#/components/responses/NotImplemented'
'502':
$ref: '#/components/responses/BadGateway'
'503':
$ref: '#/components/responses/ServiceUnavailable'
'508':
$ref: '#/components/responses/LoopDetected'
'429':
$ref: '#/components/responses/TooManyRequests'
/images:
post:
tags: [Transform]
summary: Transform an uploaded image
description: |
Private upload-and-transform endpoint.
Send a `multipart/form-data` body with a required `file` part containing the
source image or SVG, plus an optional `options` part containing JSON that
matches `ImageTransformOptions`.
This endpoint is useful when the caller already has the source bytes in hand
and does not want to make the server read from a path or remote URL.
This operation reads no query parameters. A request that carries a query string
is rejected with `400 Bad Request` naming the parameters it carried.
operationId: transformUploadedImage
security:
- BearerAuth: []
requestBody:
required: true
content:
multipart/form-data:
schema:
$ref: '#/components/schemas/UploadImageTransformRequest'
encoding:
options:
contentType: application/json
responses:
'200':
$ref: '#/components/responses/ImageBinary'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'406':
$ref: '#/components/responses/NotAcceptable'
'413':
$ref: '#/components/responses/PayloadTooLarge'
'415':
$ref: '#/components/responses/UnsupportedMediaType'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'500':
$ref: '#/components/responses/InternalError'
'501':
$ref: '#/components/responses/NotImplemented'
'503':
$ref: '#/components/responses/ServiceUnavailable'
'429':
$ref: '#/components/responses/TooManyRequests'
/health:
get:
tags: [Health]
summary: Comprehensive health diagnostic
description: |
Human-oriented diagnostic endpoint that returns version information,
process uptime, and detailed readiness checks.
Also supports `HEAD` requests.
This endpoint always returns 200 OK, even when individual checks fail,
because it is designed for dashboards and operators who need to see the
full picture.
operationId: getHealth
security:
- {}
- BearerAuth: []
responses:
'200':
description: Comprehensive health diagnostic
content:
application/json:
schema:
$ref: '#/components/schemas/HealthDiagnosticResponse'
example:
status: ok
service: truss
version: 0.24.0
uptimeSeconds: 3600
checks:
- name: storageRoot
status: ok
- name: cacheDiskFree
status: ok
freeBytes: 53687091200
thresholdBytes: 1073741824
- name: transformCapacity
status: ok
current: 2
max: 64
- name: memoryUsage
status: ok
rssBytes: 134217728
thresholdBytes: 536870912
maxInputPixels: 40000000
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/TooManyRequests'
head:
tags: [Health]
summary: Inspect comprehensive health diagnostic headers
description: |
Same contract as `GET /health`, but returns headers only and no body.
operationId: headHealth
security:
- {}
- BearerAuth: []
responses:
'200':
description: Comprehensive health diagnostic
content:
application/json:
schema:
$ref: '#/components/schemas/HealthDiagnosticResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/TooManyRequests'
/health/live:
get:
tags: [Health]
summary: Liveness probe
description: |
Lightweight liveness probe for container orchestrators (e.g. Kubernetes
`livenessProbe`). Returns immediately with minimal information confirming
the process is running and can serve HTTP. Does not check external
dependencies. Also supports `HEAD` requests.
operationId: getLiveHealth
responses:
'200':
description: Process is alive
content:
application/json:
schema:
$ref: '#/components/schemas/LivenessResponse'
example:
status: ok
service: truss
version: 0.24.0
'429':
$ref: '#/components/responses/TooManyRequests'
head:
tags: [Health]
summary: Inspect liveness probe headers
description: |
Same contract as `GET /health/live`, but returns headers only and no body.
operationId: headLiveHealth
responses:
'200':
description: Process is alive
content:
application/json:
schema:
$ref: '#/components/schemas/LivenessResponse'
'429':
$ref: '#/components/responses/TooManyRequests'
/health/ready:
get:
tags: [Health]
summary: Readiness probe
description: |
Readiness probe for container orchestrators (e.g. Kubernetes
`readinessProbe`). Also supports `HEAD` requests. Checks that the server
is able to accept traffic by verifying the storage root is accessible,
the cache root (if configured) is accessible, the object-storage backend
(if configured) is network-reachable, cache disk free space is above the
configured threshold (`TRUSS_HEALTH_CACHE_MIN_FREE_BYTES`), process memory
usage is below the configured limit (`TRUSS_HEALTH_MAX_MEMORY_BYTES`).
Transform capacity is reported in the `transformCapacity` check as
`current` against `max`, and does not affect readiness. A server with
every slot in use is doing what it was configured to do and is answering
what it accepted; withdrawing it from the load balancer would move its
share to its peers. A request that finds no free slot and no cached
answer is shed individually with 503 and a `Retry-After`.
During graceful shutdown (after SIGTERM/SIGINT on Unix, or any console
control event on Windows: Ctrl+C, Ctrl+Break, console close, log off,
or system shutdown — Windows never raises SIGTERM), this endpoint
immediately returns 503 with a `draining` check set to `fail`, even
before the drain period (`TRUSS_SHUTDOWN_DRAIN_SECS`, default 10s)
expires. This
allows load balancers and CDN edges to remove the instance from
rotation before the server stops accepting connections.
**Platform note:** RSS memory and cache disk free space are read on
Linux only. On other platforms `TRUSS_HEALTH_MAX_MEMORY_BYTES` and
`TRUSS_HEALTH_CACHE_MIN_FREE_BYTES` are effectively no-ops — those
checks are omitted from the response and the remaining checks
(object-storage reachability, storage root, etc.) still apply.
The object-storage reachability check (S3, GCS, or Azure) confirms
that the configured bucket/container exists and the service responds to
requests. It does **not** verify IAM permissions for individual
objects — a 403 AccessDenied response still counts as "reachable"
because it proves the service is up and the bucket name is correct.
Permission errors on actual object reads are surfaced as 403 on the
transform endpoints.
Returns 503 Service Unavailable when any check fails, signalling that
traffic should be routed elsewhere.
operationId: getReadyHealth
responses:
'200':
description: Server is ready to accept traffic
content:
application/json:
schema:
$ref: '#/components/schemas/ReadinessResponse'
examples:
filesystem:
summary: Filesystem backend
value:
status: ok
checks:
- name: storageRoot
status: ok
s3:
summary: S3 backend
value:
status: ok
checks:
- name: storageRoot
status: ok
- name: storageBackend
status: ok
gcs:
summary: GCS backend
value:
status: ok
checks:
- name: storageRoot
status: ok
- name: storageBackend
status: ok
azure:
summary: Azure Blob Storage backend
value:
status: ok
checks:
- name: storageRoot
status: ok
- name: storageBackend
status: ok
'503':
description: Server is not ready to accept traffic
content:
application/json:
schema:
$ref: '#/components/schemas/ReadinessResponse'
examples:
storageRootFail:
summary: Storage root inaccessible
value:
status: fail
checks:
- name: storageRoot
status: fail
draining:
summary: Graceful shutdown in progress
value:
status: fail
checks:
- name: draining
status: fail
'429':
$ref: '#/components/responses/TooManyRequests'
head:
tags: [Health]
summary: Inspect readiness probe headers
description: |
Same contract as `GET /health/ready`, but returns headers only and no body.
operationId: headReadyHealth
responses:
'200':
description: Server is ready to accept traffic
content:
application/json:
schema:
$ref: '#/components/schemas/ReadinessResponse'
'503':
description: Server is not ready to accept traffic
content:
application/json:
schema:
$ref: '#/components/schemas/ReadinessResponse'
'429':
$ref: '#/components/responses/TooManyRequests'
/metrics:
get:
tags: [Observability]
summary: Prometheus metrics
description: |
Returns metrics in Prometheus text exposition format (version 0.0.4).
Also supports `HEAD` requests.
By default, the endpoint does not require authentication. Operators can
restrict access via `TRUSS_METRICS_TOKEN` (Bearer token) or disable the
endpoint entirely via `TRUSS_DISABLE_METRICS`.
operationId: getMetrics
security:
- {}
- BearerAuth: []
responses:
'200':
description: Prometheus text exposition format
content:
text/plain:
schema:
type: string
example: |
# HELP truss_process_up Whether the process is running.
# TYPE truss_process_up gauge
truss_process_up 1
# HELP truss_http_requests_total Total HTTP requests handled.
# TYPE truss_http_requests_total counter
truss_http_requests_total 42
# HELP truss_http_request_duration_seconds HTTP request duration in seconds.
# TYPE truss_http_request_duration_seconds histogram
truss_http_request_duration_seconds_bucket{route="/health",le="0.005"} 10
truss_http_request_duration_seconds_bucket{route="/health",le="+Inf"} 10
truss_http_request_duration_seconds_sum{route="/health"} 0.002
truss_http_request_duration_seconds_count{route="/health"} 10
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'503':
$ref: '#/components/responses/ServiceUnavailable'
'429':
$ref: '#/components/responses/TooManyRequests'
head:
tags: [Observability]
summary: Inspect Prometheus metrics headers
description: |
Same contract as `GET /metrics`, but returns headers only and no body.
operationId: headMetrics
security:
- {}
- BearerAuth: []
responses:
'200':
description: Prometheus text exposition format
content:
text/plain:
schema:
type: string
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'503':
$ref: '#/components/responses/ServiceUnavailable'
'429':
$ref: '#/components/responses/TooManyRequests'
components:
securitySchemes:
SignedUrlAuth:
type: apiKey
in: query
name: signature
description: |
HMAC-SHA256 signed URL authentication.
Requires `keyId`, `expires`, and `signature` query parameters on public
image endpoints.
The canonical form is:
`METHOD\nAUTHORITY\nREQUEST_PATH\nCANONICAL_QUERY`
In practice, callers usually generate these URLs with `truss sign` or an
equivalent implementation that matches the server's canonicalization rules.
BearerAuth:
type: http
scheme: bearer
bearerFormat: opaque
description: |
Bearer token authentication for private server-to-server and upload endpoints.
parameters:
SourcePath:
name: path
in: query
required: true
description: |
Source path resolved relative to `TRUSS_STORAGE_ROOT`.
A leading slash is allowed, but the final resolved path must stay under the
storage root.
schema:
type: string
minLength: 1
example: /photos/hero.jpg
SourceUrl:
name: url
in: query
required: true
description: |
Remote HTTP(S) URL to fetch the source image from.
Private-network and loopback targets may be rejected depending on server configuration.
schema:
type: string
format: uri
example: https://example.com/images/hero.png
SourceVersion:
name: version
in: query
required: false
description: |
Optional cache-busting version tag for the source.
This value becomes part of the cache key but is not fetched from the origin.
schema:
type: string
minLength: 1
example: v3
KeyId:
name: keyId
in: query
required: true
description: Key identifier that selects the shared secret used for signed URL verification.
schema:
type: string
minLength: 1
example: public-demo
Expires:
name: expires
in: query
required: true
description: |
Expiration time as a Unix timestamp in seconds.
Requests are rejected after this instant.
schema:
type: integer
format: int64
minimum: 1
example: 1893456000
Signature:
name: signature
in: query
required: true
description: Lowercase hex-encoded HMAC-SHA256 signature
schema:
type: string
minLength: 1
example: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
Width:
name: width
in: query
required: false
description: |
Requested output width in pixels.
When `height` is omitted, the image is resized proportionally.
schema:
type: integer
minimum: 1
example: 1200
Height:
name: height
in: query
required: false
description: |
Requested output height in pixels.
When `width` is omitted, the image is resized proportionally.
schema:
type: integer
minimum: 1
example: 630
Fit:
name: fit
in: query
required: false
description: |
Resize strategy. Only meaningful when both width and height are set.
Defaults to `contain`.
- `contain`: fit inside the box, then pad to the exact box
- `cover`: fill the box, cropping the excess
- `fill`: stretch each axis to the box, ignoring aspect ratio
- `inside`: fit inside the box with no padding; the output is at most the
requested size and usually smaller on one axis
`contain` and `inside` scale identically and differ only in the padding, so a
640x427 source in a 200x200 box is 200x200 under `contain` and 200x133 under
`inside`. Whether a smaller source may be scaled up is `withoutEnlargement`,
not part of any fit mode.
schema:
type: string
enum: [contain, cover, fill, inside]
default: contain
example: cover
Position:
name: position
in: query
required: false
description: |
Crop anchor for cover mode and padding placement.
Only meaningful when both width and height are set.
Defaults to `center`.
schema:
type: string
enum: [center, top, right, bottom, left, top-left, top-right, bottom-left, bottom-right]
default: center
example: top
Format:
name: format
in: query
required: false
description: |
Output image format.
When present, the `Accept` header is ignored.
`svg` output is only valid for SVG input, and is a sanitize-only passthrough: the
document is returned as written, so `width`, `height`, `rotate`, `grayscale`, and
`background` return 400 naming the parameter instead of being ignored. Request a
raster format to transform the drawing.
`gif` is not an output format: truss decodes GIF but does not encode it, so
requesting it returns 415. A GIF source with no `format` is served as PNG.
A source with more than one frame is rejected with 415 rather than reduced to
one frame, whether it is a GIF, an animated WebP, an APNG, or an animated AVIF.
schema:
type: string
enum: [jpeg, png, webp, avif, bmp, tiff, svg]
example: webp
Quality:
name: quality
in: query
required: false
description: |
Encoding quality for lossy formats (jpeg, webp, avif).
Returns 400 for lossless formats.
schema:
type: integer
minimum: 1
maximum: 100
example: 82
Optimize:
name: optimize
in: query
required: false
description: |
Optimization mode for the final encoding stage.
`none` preserves the existing behavior.
`auto` picks a format-appropriate strategy.
`lossless` uses only pixel-preserving techniques, and is answered
`501 Not Implemented` for AVIF output: the AV1 encoder truss reaches
offers a quality setting and no bit-exact mode, and a near-lossless
encode is not what the name promises. Use `auto` for the smallest
AVIF, or a lossless format for bit-exact pixels.
`lossy` may reduce quality to save more bytes.
schema:
type: string
enum: [none, auto, lossless, lossy]
default: none
example: auto
TargetQuality:
name: targetQuality
in: query
required: false
description: |
Perceptual target used by lossy optimization, for example `ssim:0.98`
or `psnr:42`. Requires `optimize=auto` or `optimize=lossy`.
SSIM must be in `(0,1]`; PSNR must be greater than `0`.
schema:
oneOf:
- type: string
pattern: '^ssim:(?:0\.[0-9]*[1-9][0-9]*|1(?:\.0+)?)$'
- type: string
pattern: '^psnr:(?:0\.[0-9]*[1-9][0-9]*|[1-9][0-9]*(?:\.[0-9]+)?)$'
example: ssim:0.98
Background:
name: background
in: query
required: false
description: |
Background color as RRGGBB or RRGGBBAA hex (no leading #).
Mainly visible when padding or flattening transparency into opaque formats.
schema:
type: string
pattern: '^[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$'
example: ffffff
Rotate:
name: rotate
in: query
required: false
description: |
Clockwise rotation in whole degrees, applied after EXIF auto-orient.
Any integer is accepted: a negative angle turns counter-clockwise and an angle past
a full turn wraps, so `-90` and `270` are the same rotation.
The signature covers the query string as sent, so a signed URL must spell the value
the same way it was signed; `truss sign` and `@nao1215/truss-url-signer` both write
the wrapped 0-359 form.
A multiple of 90 is exact. Any other angle resamples and grows the output to the
rotated bounding box, filling the exposed corners with `background`
(transparent by default, white for formats without an alpha channel).
schema:
type: integer
default: 0
example: 45
AutoOrient:
name: autoOrient
in: query
required: false
description: |
Apply EXIF orientation when the input provides it, then reset the orientation tag.
Read from JPEG, PNG, WebP, and TIFF, which are the containers that can carry it.
schema:
type: boolean
default: true
example: true
StripMetadata:
name: stripMetadata
in: query
required: false
description: |
Remove metadata from the output when `true`.
Set this to `false` to keep supported metadata where the output encoder can retain it.
schema:
type: boolean
default: true
example: true
PreserveExif:
name: preserveExif
in: query
required: false
description: |
Preserve EXIF data only. Implies `stripMetadata=false`, so it does not have to be
sent alongside; an explicit `stripMetadata=true` is overridden rather than refused.
When `stripMetadata=false` and `preserveExif=false`, the server keeps all metadata
that the selected output encoder supports.
Returns 400 when output format is SVG.
schema:
type: boolean
default: false
example: false
Crop:
name: crop
in: query
required: false
description: |
Explicit pixel crop as `x,y,width,height`.
Applied after auto-orient and rotation but before resize.
The region must fit within the (possibly rotated) source dimensions.
Not supported for SVG inputs.
schema:
type: string
pattern: '^\d+,\d+,[1-9]\d*,[1-9]\d*$'
example: "100,50,800,600"
Preset:
name: preset
in: query
required: false
description: |
Name of a server-side transform preset.
Presets are defined via `TRUSS_PRESETS` or `TRUSS_PRESETS_FILE`.
Explicit query parameters override preset values.
schema:
type: string
minLength: 1
example: thumbnail
Blur:
name: blur
in: query
required: false
description: |
Apply Gaussian blur with the given sigma value.
Valid range is 0.1 to 100.0. Higher values produce a stronger blur.
Not supported for SVG inputs.
schema:
type: number
format: float
minimum: 0.1
maximum: 100.0
example: 3.0
Sharpen:
name: sharpen
in: query
required: false
description: |
Apply unsharp-mask (sharpen) filter with the given sigma value.
Valid range is 0.1 to 100.0. Higher values produce stronger sharpening.
Not supported for SVG inputs.
schema:
type: number
format: float
minimum: 0.1
maximum: 100.0
example: 2.0
WithoutEnlargement:
name: withoutEnlargement
in: query
required: false
description: |
Never scale an image up to reach the requested size. A source already within the
requested bounds keeps its own size.
Independent of `fit`, and meaningful for a single-axis resize too. `contain` still
pads out to the full requested box; only the content inside it stops growing.
`cover` returns the requested box intersected with the source instead of the whole
box, because a crop cannot return more canvas than there is content.
Requires `width` or `height`.
schema:
type: boolean
default: false
example: true
Grayscale:
name: grayscale
in: query
required: false
description: |
Desaturate the image to grayscale. Luminance uses the Rec. 601 weights and the
alpha channel is preserved. Applied after resize, blur, and sharpen, and before
the watermark, so a watermark keeps its own colors.
For SVG sources it applies to the rasterized output; SVG-to-SVG output ignores it.
schema:
type: boolean
default: false
example: true
WatermarkUrl:
name: watermarkUrl
in: query
required: false
description: |
HTTP(S) URL of a watermark image to composite onto the output.
Must be a raster format (PNG, JPEG, WebP, BMP, TIFF); SVG is not supported.
Subject to SSRF protection and the remote watermark size limit
(`TRUSS_MAX_WATERMARK_BYTES`, default 10 MB).
For multipart uploads the `watermark` file field has a fixed 10 MB cap.
schema:
type: string
format: uri
example: https://example.com/logo.png
WatermarkPosition:
name: watermarkPosition
in: query
required: false
description: |
Where to place the watermark on the output image.
Requires `watermarkUrl` to be set; requests are rejected otherwise.
schema:
type: string
enum: [center, top, right, bottom, left, top-left, top-right, bottom-left, bottom-right]
default: bottom-right
example: bottom-right
WatermarkOpacity:
name: watermarkOpacity
in: query
required: false
description: |
Watermark opacity (1–100).
Requires `watermarkUrl` to be set; requests are rejected otherwise.
schema:
type: integer
minimum: 1
maximum: 100
default: 50
example: 50
WatermarkMargin:
name: watermarkMargin
in: query
required: false
description: |
Margin in pixels from the nearest edge.
Requires `watermarkUrl` to be set; requests are rejected otherwise.
schema:
type: integer
minimum: 0
default: 10
example: 10
schemas:
PathImageSource:
type: object
description: Source image stored under the server's configured storage root.
additionalProperties: false
required: [kind, path]
properties:
kind:
type: string
enum: [path]
path:
type: string
minLength: 1
version:
type: string
minLength: 1
example:
kind: path
path: /photos/hero.jpg
version: v3
UrlImageSource:
type: object
description: Source image fetched from a remote HTTP(S) URL.
additionalProperties: false
required: [kind, url]
properties:
kind:
type: string
enum: [url]
url:
type: string
format: uri
version:
type: string
minLength: 1
example:
kind: url
url: https://example.com/images/hero.png
version: v3
StorageImageSource:
type: object
description: |
Source image stored in an S3-compatible, GCS, or Azure Blob Storage
backend. Requires the `s3`, `gcs`, or `azure` feature and the
corresponding `TRUSS_STORAGE_BACKEND` value.
additionalProperties: false
required: [kind, key]
properties:
kind:
type: string
enum: [storage]
bucket:
type: string
minLength: 1
description: >-
Bucket name (or Azure container name). Defaults to
`TRUSS_S3_BUCKET`, `TRUSS_GCS_BUCKET`, or `TRUSS_AZURE_CONTAINER`
when omitted.
key:
type: string
minLength: 1
description: Object key within the bucket (or Azure container).
version:
type: string
minLength: 1
example:
kind: storage
key: photos/hero.jpg
ImageSource:
description: >-
Exactly one source descriptor: a storage path, a remote URL, or an
object-storage reference.
oneOf:
- $ref: '#/components/schemas/PathImageSource'
- $ref: '#/components/schemas/UrlImageSource'
- $ref: '#/components/schemas/StorageImageSource'
discriminator:
propertyName: kind
mapping:
path: '#/components/schemas/PathImageSource'
url: '#/components/schemas/UrlImageSource'
storage: '#/components/schemas/StorageImageSource'
ImageTransformOptions:
type: object
description: |
Shared transform options used by the JSON and multipart endpoints.
The same semantics also apply to equivalent query parameters on public GET endpoints.
additionalProperties: false
properties:
width:
type: integer
minimum: 1
description: Requested output width in pixels.
height:
type: integer
minimum: 1
description: Requested output height in pixels.
fit:
type: string
enum: [contain, cover, fill, inside]
default: contain
description: >-
Resize strategy used when both width and height are present. `contain` and
`inside` scale identically; `contain` pads the result out to the exact box and
`inside` returns it unpadded, so `inside` output is usually smaller than the
requested size on one axis.
position:
type: string
enum: [center, top, right, bottom, left, top-left, top-right, bottom-left, bottom-right]
default: center
description: Crop anchor or padding placement for bounded resizes.
format:
type: string
enum: [jpeg, png, webp, avif, bmp, tiff, svg]
description: Explicit output format. When omitted, the server negotiates or keeps the input format.
quality:
type: integer
minimum: 1
maximum: 100
description: Quality for lossy outputs (`jpeg`, `webp`, `avif`).
optimize:
type: string
enum: [none, auto, lossless, lossy]
default: none
description: Optimization mode for the final encoding stage.
targetQuality:
description: >-
Perceptual target used by lossy optimization, for example
`ssim:0.98` or `psnr:42`. SSIM must be in `(0,1]`; PSNR must be
greater than `0`. Requires `optimize=auto` or `optimize=lossy`.
oneOf:
- type: string
pattern: '^ssim:(?:0\.[0-9]*[1-9][0-9]*|1(?:\.0+)?)$'
- type: string
pattern: '^psnr:(?:0\.[0-9]*[1-9][0-9]*|[1-9][0-9]*(?:\.[0-9]+)?)$'
background:
type: string
pattern: '^[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$'
description: Background color for padding or flattening transparency.
rotate:
type: integer
default: 0
description: >-
Extra clockwise rotation in whole degrees, applied after auto-orientation.
Negative turns counter-clockwise and angles past a full turn wrap. A multiple of
90 is exact; any other angle resamples and grows the output to the rotated
bounding box, filling the exposed corners with `background`.
autoOrient:
type: boolean
default: true
description: Apply EXIF orientation when present, in JPEG, PNG, WebP, or TIFF.
stripMetadata:
type: boolean
default: true
description: Remove metadata from the output when `true`.
preserveExif:
type: boolean
default: false
description: Preserve EXIF only. Implies `stripMetadata=false`.
crop:
type: string
pattern: '^\d+,\d+,[1-9]\d*,[1-9]\d*$'
description: >-
Explicit pixel crop as `x,y,width,height`. Applied after auto-orient
and rotation but before resize. Not supported for SVG inputs.
blur:
type: number
format: float
minimum: 0.1
maximum: 100.0
description: >-
Gaussian blur sigma (0.1–100.0). Higher values produce a stronger blur.
Not supported for SVG inputs; the server will reject the request
with an error if blur is specified for an SVG source.
sharpen:
type: number
format: float
minimum: 0.1
maximum: 100.0
description: >-
Sharpen sigma (0.1–100.0). Higher values produce stronger sharpening.
Not supported for SVG inputs; the server will reject the request
with an error if sharpen is specified for an SVG source.
withoutEnlargement:
type: boolean
default: false
description: >-
Never scale an image up to reach the requested size. Independent of `fit` and
meaningful for a single-axis resize too; `contain` still pads out to the full
box. Requires width or height.
grayscale:
type: boolean
default: false
description: >-
Desaturate the image to grayscale using Rec. 601 luminance weights, preserving
alpha. Applied after resize, blur, and sharpen, and before the watermark.
For SVG sources it applies to the rasterized output; SVG-to-SVG output ignores it.
preset:
type: string
minLength: 1
description: >-
Name of a server-side transform preset. Explicit fields override preset values.
example:
width: 1600
height: 900
fit: cover
position: center
format: webp
quality: 82
optimize: auto
targetQuality: ssim:0.98
autoOrient: true
stripMetadata: true
WatermarkPayload:
type: object
description: |
Watermark overlay configuration for the JSON transform endpoint.
The `url` field is required and must point to a raster image (PNG, JPEG, WebP, BMP, TIFF).
SVG watermarks are not supported.
additionalProperties: false
required: [url]
properties:
url:
type: string
format: uri
description: HTTP(S) URL of the watermark image. Subject to SSRF protection.
position:
type: string
enum: [center, top, right, bottom, left, top-left, top-right, bottom-left, bottom-right]
default: bottom-right
description: Where to place the watermark on the output image.
opacity:
type: integer
minimum: 1
maximum: 100
default: 50
description: Watermark opacity (1–100).
margin:
type: integer
minimum: 0
default: 10
description: Margin in pixels from the nearest edge.
example:
url: https://example.com/logo.png
position: bottom-right
opacity: 50
margin: 10
TransformImageRequest:
type: object
description: JSON request body for transforming a path- or URL-based source.
additionalProperties: false
required: [source]
properties:
source:
$ref: '#/components/schemas/ImageSource'
options:
$ref: '#/components/schemas/ImageTransformOptions'
watermark:
$ref: '#/components/schemas/WatermarkPayload'
example:
source:
kind: path
path: /photos/hero.jpg
options:
width: 1600
format: webp
quality: 82
optimize: auto
UploadImageTransformRequest:
type: object
description: |
Multipart request body containing the source file, optional transform options,
and optional watermark overlay fields.
additionalProperties: false
required: [file]
properties:
file:
type: string
format: binary
description: The image or SVG file to transform.
options:
$ref: '#/components/schemas/ImageTransformOptions'
watermark:
type: string
format: binary
description: Watermark image file (PNG, JPEG, WebP, BMP, or TIFF). SVG is not supported.
watermark_position:
type: string
enum: [center, top, right, bottom, left, top-left, top-right, bottom-left, bottom-right]
default: bottom-right
description: Where to place the watermark on the output image. Requires a `watermark` file field.
watermark_opacity:
type: integer
minimum: 1
maximum: 100
default: 50
description: Watermark opacity (1–100). Requires a `watermark` file field.
watermark_margin:
type: integer
minimum: 0
default: 10
description: Margin in pixels from the nearest edge. Requires a `watermark` file field.
LivenessResponse:
type: object
description: Minimal liveness payload confirming the process is running.
additionalProperties: false
required: [status, service, version]
properties:
status:
type: string
enum: [ok]
service:
type: string
enum: [truss]
version:
type: string
description: Semantic version of the running binary.
example: "0.24.0"
ReadinessResponse:
type: object
description: Readiness payload with individual dependency checks.
additionalProperties: false
required: [status, checks]
properties:
status:
type: string
enum: [ok, fail]
checks:
type: array
items:
$ref: '#/components/schemas/HealthCheck'
HealthDiagnosticResponse:
type: object
description: Comprehensive diagnostic payload with version, uptime, and checks.
additionalProperties: false
required: [status, service, version, uptimeSeconds, checks, maxInputPixels]
properties:
status:
type: string
enum: [ok, fail]
service:
type: string
enum: [truss]
version:
type: string
description: Semantic version of the running binary.
example: "0.24.0"
uptimeSeconds:
type: integer
format: int64
minimum: 0
description: Seconds since the server process started.
checks:
type: array
items:
$ref: '#/components/schemas/HealthCheck'
maxInputPixels:
type: integer
format: int64
minimum: 1
description: Maximum input image pixel count allowed before decode.
HealthCheck:
type: object
description: Individual dependency check result.
additionalProperties: false
required: [name, status]
properties:
name:
type: string
description: Name of the checked dependency.
example: storageRoot
status:
type: string
enum: [ok, fail]
freeBytes:
type: integer
format: int64
minimum: 0
description: Free bytes on the cache disk (cacheDiskFree check only).
thresholdBytes:
type: integer
format: int64
minimum: 1
description: >-
Configured threshold in bytes. Present on cacheDiskFree and
memoryUsage checks when a threshold is configured.
rssBytes:
type: integer
format: int64
minimum: 0
description: Process resident set size in bytes (memoryUsage check only, Linux).
current:
type: integer
format: int64
minimum: 0
description: Current number of in-flight transforms (transformCapacity check only).
max:
type: integer
format: int64
minimum: 1
description: Maximum concurrent transforms allowed (transformCapacity check only).
recovering:
type: boolean
description: Present and `true` while a hysteresis-tracked resource check remains in its recovery margin.
ProblemDetail:
type: object
description: |
RFC 9457 Problem Details. `type` is the member to branch on: it is a URI naming the
class of failure, an anchor on `docs/problems.md`, and `about:blank` only for a route
that does not exist. `title` is fixed per class; `detail` is for a person to read and
its wording is not part of the API. `requestId` repeats the `X-Request-Id` header.
required: [type, title, status, detail, requestId]
properties:
type:
type: string
format: uri
example: "https://github.com/nao1215/truss/blob/main/docs/problems.md#invalid-request"
title:
type: string
example: "Invalid request"
status:
type: integer
example: 400
detail:
type: string
example: "missing required query parameter: path"
requestId:
type: string
example: "6b3d0a2c-2f6a-4c53-9a1f-0f4b2c1e8d7a"
responses:
ImageBinary:
description: |
Transformed image or sanitized SVG bytes.
The exact response media type depends on the selected output format.
headers:
Cache-Control:
description: |
`public, max-age=3600, stale-while-revalidate=60` for public GET endpoints.
`no-store` for private endpoints.
schema:
type: string
ETag:
description: SHA-256 based entity tag in the form `"sha256-<hex>"`
schema:
type: string
Vary:
description: Set to `Accept` whenever the output format was left to content negotiation, including when the request sent no `Accept` header. Absent when the request named a format explicitly or negotiation is disabled server-side.
schema:
type: string
Cache-Status:
description: RFC 9211 cache status (`"truss"; hit` or `"truss"; fwd=miss`)
schema:
type: string
Age:
description: Seconds since the response was cached (only on cache hits)
schema:
type: integer
Truss-Warning:
description: |
One header per transform warning: a result that is not quite what was asked
for, such as an EXIF orientation dropped with `autoOrient=false`, a
`targetQuality` the encode did not reach, or metadata the output format
cannot carry. The text is the same the CLI prints after `warning:` and the Wasm
package returns in `warnings`. A cache hit repeats the headers the original
transform produced; a 304 carries none.
schema:
type: string
X-Content-Type-Options:
description: Always set to `nosniff`
schema:
type: string
Content-Disposition:
description: Always `inline; filename="truss.<ext>"`
schema:
type: string
Content-Security-Policy:
description: Set to `sandbox` for SVG output only
schema:
type: string
content:
image/jpeg:
schema:
type: string
format: binary
image/png:
schema:
type: string
format: binary
image/webp:
schema:
type: string
format: binary
image/avif:
schema:
type: string
format: binary
image/bmp:
schema:
type: string
format: binary
image/tiff:
schema:
type: string
format: binary
image/svg+xml:
schema:
type: string
format: binary
NotModified:
description: ETag matched the If-None-Match header (GET and HEAD)
headers:
ETag:
schema:
type: string
Cache-Control:
schema:
type: string
Cache-Status:
schema:
type: string
Vary:
description: Set to `Accept` under the same rule as the 200 response, because a 304 selects the same representation
schema:
type: string
BadRequest:
description: Invalid request parameters or body
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
example:
type: https://github.com/nao1215/truss/blob/main/docs/problems.md#invalid-options
title: Invalid transform options
status: 400
detail: fit requires both width and height
requestId: 6b3d0a2c-2f6a-4c53-9a1f-0f4b2c1e8d7a
Unauthorized:
description: Authentication failed or missing
headers:
WWW-Authenticate:
description: Set to `Bearer` for Bearer token endpoints
schema:
type: string
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
Forbidden:
description: Access denied (e.g. path traversal attempt)
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
NotFound:
description: Source file or route not found
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
NotAcceptable:
description: |
`Accept` header negotiation failed because none of the requested response media types
matched the formats supported by the server.
headers:
Vary:
description: Always `Accept`, because this response was selected by the `Accept` header
schema:
type: string
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
PayloadTooLarge:
description: Request body or remote source exceeds size limit
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
UnprocessableEntity:
description: Input image exceeds the configured pixel limit (`TRUSS_MAX_INPUT_PIXELS`)
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
example:
type: https://github.com/nao1215/truss/blob/main/docs/problems.md#unprocessable-entity
title: Unprocessable Entity
status: 422
detail: "input image has 50000000 pixels, server limit is 40000000"
requestId: 6b3d0a2c-2f6a-4c53-9a1f-0f4b2c1e8d7a
UnsupportedMediaType:
description: |
Unsupported input format, unsupported output format, or wrong request `Content-Type`.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
InternalError:
description: Internal server error
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
NotImplemented:
description: Requested transform is not supported
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
BadGateway:
description: Remote origin fetch failed
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
ServiceUnavailable:
description: |
Server overloaded or required configuration missing. `Retry-After` is
present when waiting is what resolves the condition, which is the case
for a request shed because every transform slot is in use, and absent
when the cause is a configuration the process cannot resolve by waiting.
headers:
Retry-After:
description: Seconds to wait before retrying the request
schema:
type: integer
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
TooManyRequests:
description: Request was rejected by the per-IP rate limiter
headers:
Retry-After:
description: Seconds to wait before retrying the request
schema:
type: integer
X-Request-Id:
schema:
type: string
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
LoopDetected:
description: Too many redirects when fetching remote source
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'