Skip to content

Media overview

TEBHOS serves media from three places. Knowing which one a URL belongs to tells you which query parameters it accepts and which headers it returns.

Surface Base URL Serves
Media routes endpoints.media (https://tebhos.com/api/v1) Avatars, banners, guild icons and other hash-addressed images, resized on request; any stored object by key through /files/{key}
Uploaded-file CDN https://cdn.tebhos.com Stored objects as uploaded: message attachments, custom emoji and sticker images, entrance sounds, group DM icons and other files
Media proxy https://tebhos.com Signed external media (/external/...) and OpenGraph metadata (/og)

Take endpoints.media from instance discovery rather than hard-coding it. URLs to CDN objects are always returned by the API in full (for example an attachment's url), so you never build them yourself.

Route families

Family Paths Reference
Image asset /avatars, /banners, /server-icons, /server-banners, /server-invite-bg, /server-embed-bg, /live-room-banners under endpoints.media Image asset contract
Stored object /files/{key} under endpoints.media Get stored object
Signed external /external/{signature}/v2/{target} Get signed external media
OpenGraph /og?url= Get OpenGraph metadata
Signing GET /media/sign on the HTTP API Sign an external URL

Transformations defines the query parameters that select a size, format and animation. Responses and limits lists statuses, size bounds, deadlines and cache policies.

Not supported on TEBHOS

TEBHOS has no signed attachment URLs (ex, is, hm query parameters), no upload relay, and no separate theme or entrance-sound read routes. Attachments and other uploads are plain CDN URLs; uploads go straight to storage through presigned URLs, see Uploads.

Authorisation

No media read route reads the Authorization header. Image assets and stored objects are authorised by their path alone, and signed external media by the signature in its path.

A media URL is a bearer capability

Anyone who has a media URL can fetch the object without an account, and leaving a guild or channel does not revoke a URL you already received. Storage keys and content hashes are long and unguessable, but treat media URLs you did not publish as private.

The only authenticated operation on this surface is signing an external URL, which needs a signed-in user session.

Rate limits

Media reads have no request-count rate limit. GET and HEAD requests to the media routes are exempt from the HTTP API global rate limit, and the media proxy has no limiter, so no media response carries rate limit headers.

Methods

The media routes under endpoints.media accept GET and HEAD. HEAD returns the same status and headers as GET with an empty body, including Content-Length.

The media proxy routes (/external/... and /og) accept GET only.

Cross-origin reads

Every successful media route response under endpoints.media has Access-Control-Allow-Origin: *, whatever Origin the request sent, and its Vary header never contains Origin. Browsers and the desktop app therefore share one cache entry per URL.

The media proxy allows cross-origin GET only from the TEBHOS web app origins (https://tebhos.com and its subdomains). A plain <img> or <video> element does not send Origin and loads from any page.

Byte ranges

The media routes under endpoints.media honour a single byte range on the selected representation (after any transformation).

Value Description
bytes={start}-{end} Selects the inclusive interval; an end beyond the representation is clamped
bytes={start}- Selects from start through the final byte
bytes=-{length} Selects the final length bytes

A satisfiable range returns 206 with Content-Range: bytes {start}-{end}/{size}. A reversed range, a zero-length suffix, a start outside the representation, or any range over an empty representation returns 416 with Content-Range: bytes */{size} and an empty body. A value whose unit is not bytes=, or that names more than one range (contains a comma), is ignored and the complete representation is returned.

The media proxy does not forward or honour Range.

Representation headers

Successful responses from the image asset and stored object routes carry:

Header Description
Content-Type The media type of the returned bytes (detected from the content, not the file name)
Content-Length Length of the returned body, also on HEAD
Content-Range? Present on 206
Accept-Ranges Always bytes
Access-Control-Allow-Origin Always *
Cache-Control See cache policies
CDN-Cache-Control public, max-age=31536000
Vary Accept-Encoding, or Accept, Accept-Encoding when the format was negotiated from Accept
X-Content-Type-Options Always nosniff
X-Robots-Tag noindex, nofollow, noimageindex
x-tebhos-media-cache hit, miss or bypass: whether the representation came from the in-memory transformation cache. Informational only

No media response has a Content-Disposition header. When you save a file, derive its extension from Content-Type.

Content detection

The media routes detect an object's type from its first bytes. Only PNG, JPEG, GIF and WebP content is served as an image asset: an object with any other content is reported as 404 on the image asset routes, and the stored object route returns it unchanged with a type derived from its key extension (see Get stored object).

On the media proxy, the origin's Content-Type decides whether the target is proxied at all, see Target validation.