## Generated Documentation

- [jellything](/doc/jellything/)
- [jellycommon](/doc/jellycommon/)
- [jellyremuxer](/doc/jellyremuxer/)
- [jellytranscode](/doc/jellytranscode/)
- [jellyimport](/doc/jellyimport/)
- [jellymatroska](/doc/jellymatroska/)
- [jellybase](/doc/jellybase/)
- [jellystream](/doc/jellystream/)
- [jellytool](/doc/jellytool/)

# Jellything HTTP API

Most endpoints require the `Accept` header to be present and set to
`application/json` and `image/avif` respectively. Any endpoint returning JSON,
will report errors with an object containing error string in the `error` key.
Routes marked with `*` require authentification.

## Rust API Wrapper

For making your own applications that implement client functionality in Rust,
use the `jellyclient` crate. The `jellycommon` crate exposes commonly used
structs like those used in the library and for jhls.

```toml
# Cargo.toml
[depedencies]
jellyclient = { git = "https://codeberg.org/metamuffin/jellything.git" }
```

## General

### GET `/api/version`

Returns API version number.

### POST `/api/create_session`

Request body contains JSON with keys `username`, `password`, `expire` (in
seconds) and `drop_permissions` (a list of permissions, that this session cannot
use). The Response contains the session cookie as a string in JSON.

### GET* `/n/<id>?<parents>&<children>&<filter..>`

Request a library node with userdata attached. If `parents` or `children` flag
is set, all parents/children will be returned too, otherwise those lists are
empty. Returns `ApiNodeResponse`.

### GET* `/n/<id>/userdata`

Returns only `NodeUserData` for that node.

### GET* `/search?<query>&<page>`

Returns `ApiSearchResponse`.

### GET* `/items?<filter..>&<page>`

Returns `ApiItemsResponse`.

### GET* `/home`

Returns `ApiHomeResponse`.

## Assets

Endpoints like `.../poster` redirect to the asset that you need and
automatically choose fallbacks. Alternatively you can directly request assets
with `/asset/<token>`, but there you need to implement the fallback behaviour
yourself. Returned images are coded with AVIF. The `width` parameter is the
width of the resolution you want to image to be.

> [!WARNING] The actual returned resolution must not be exactly what you
> requested. Currently it is rounded up to the next power of two.

### GET* `/asset/<token>?<width>`

This is the final asset endpoint where images are returned from. Other endpoints
redirect here. The `token` part is an opaque string that you obtain from
somewhere else like a redirect or from within the `Node` struct.

### GET* `/n/<id>/poster?<width>`

### GET* `/n/<id>/backdrop?<width>`

### GET* `/n/<id>/thumbnail?<t>&<width>`

Returns a single frame from some track video of the media at a given time `t`.

### GET* `/n/<id>/person/<index>/asset?<group>&<width>`

Returns headshot of a person from that node.

## Stream

### GET* `/n/<id>/stream?<params..>`

Responds with the stream directly or a redirect to the actual source in case of
federation.

- `?whep&<track...>&<seek>`
  - WHEP Endpoint for streaming that set of tracks. The format used is decided
    by the server.
- `?whepcontrol&<token>`
  - WebSocket endpoint for controlling WHEP playback. TODO schema
- `?remux&<track...>&<container>`
- `?hlssupermultivariant&<container>`
  - Returns m3u8/HLS playlist of all known multi-variant playlists, one for each
    segment. The plylist is updated for live media.
- `?hlsmultivariant&<segment>&<container>`
  - Returns m3u8/HLS playlist of all track formats' variant playlists.
- `?hlsvariant&<segment>&<track>&<container>&<format>`
  - Returns m3u8/HLS playlist of all known fragments of this track format. The
    playlist is updated for live media.
- `?info`
  - Returns JSON `StreamInfo`.
- `?fragmentindex&<segment>&<track>`
  - Returns time ranges for every fragment of this track.
- `?fragment&<segment>&<track>&<index>&<container>&<format>`

```ts
export type FragmentIndex = TimeRange[];
export interface TimeRange {
  start: number;
  end: number;
}
export interface SubtitleCue extends TimeRange {
  content: string;
}
export interface StreamInfo {
  name?: string;
  segments: SegmentInfo[];
}
export interface SegmentInfo {
  name?: string;
  duration: number;
  tracks: TrackInfo[];
}
export type TrackKind = "video" | "audio" | "subtitle";
export interface TrackInfo {
  name?: string;
  language?: string;
  kind: TrackKind;
  formats: FormatInfo[];
}
export type StreamContainer = "webm" | "matroska" | "mpeg4" | "jvtt" | "webvtt";
export interface FormatInfo {
  codec: string;
  bitrate: number;
  remux: boolean;
  containers: StreamContainer[];

  width?: number;
  height?: number;
  channels?: number;
  samplerate?: number;
  bit_depth?: number;
}
```
