# Bundles routes

The bundles routes of games-api, with parameters, bodies, responses and request samples.

Generated from `openapi.yaml` of games-api 0.7.0: 2 routes.

- [`GET /v1/bundles/{slug}/{version}/{path}`](#get-v1-bundles-slug-version-path): Bundle file, CDN origin for the game hosts
- [`GET /v1/bundles/{slug}/media/{file}`](#get-v1-bundles-slug-media-file): Game media file, CDN origin for play.filudi.com (ADR 0007)

<RouteHeading id="get-v1-bundles-slug-version-path" method="GET" path="/v1/bundles/{slug}/{version}/{path}" />

<CodePanel title="GET /v1/bundles/{slug}/{version}/{path}">
  <Fragment slot="curl">

    ```sh
    curl 'https://api.filudi.com/v1/bundles/gloop/1.0.0/index.html'
    ```

  </Fragment>
  <Fragment slot="javascript">

    ```js
    const response = await fetch('https://api.filudi.com/v1/bundles/gloop/1.0.0/index.html');
    // No body: check response.ok.
    ```

  </Fragment>
  <Fragment slot="python">

    ```py
    import requests

    response = requests.get('https://api.filudi.com/v1/bundles/gloop/1.0.0/index.html')
    response.raise_for_status()
    # No body: the status says it all.
    ```

  </Fragment>
</CodePanel>

**Bundle file, CDN origin for the game hosts**

With `PLAY_GAME_HOST_SUFFIX` set, a request without `X-Play-Host: <slug>.<suffix>` answers the
same 404 as any other miss. A request with any `X-Play-Host` ignores `preview`; a preview is a
direct request with no such header (ADR 0013). The CDN sets that header on the path players use.
With `PREVIEW_URL` set, a preview is served only on that host, which always needs a valid token,
refuses `X-Play-Host`, and answers 404 outside `/v1/bundles/*`. `_upload.zip` is always 404.

Credential: none. The route is public.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `slug` | path | string | yes |  |
| `version` | path | string | yes |  |
| `path` | path | string | yes |  |
| `preview` | query | string | no | Signed, time-limited parameter that allows a draft version |
| `X-Play-Host` | header | string | no | Hostname the player asked the CDN for |

### Responses

| Status | Body | Description |
| --- | --- | --- |
| 200 | none | File. Headers: `Cache-Control`, `Content-Security-Policy`, `Cross-Origin-Resource-Policy`. |
| 404 | [Error](/docs/api/reference/schemas/#schema-error) | Unknown resource. |

<RouteHeading id="get-v1-bundles-slug-media-file" method="GET" path="/v1/bundles/{slug}/media/{file}" />

<CodePanel title="GET /v1/bundles/{slug}/media/{file}">
  <Fragment slot="curl">

    ```sh
    curl 'https://api.filudi.com/v1/bundles/gloop/media/string'
    ```

  </Fragment>
  <Fragment slot="javascript">

    ```js
    const response = await fetch('https://api.filudi.com/v1/bundles/gloop/media/string');
    // No body: check response.ok.
    ```

  </Fragment>
  <Fragment slot="python">

    ```py
    import requests

    response = requests.get('https://api.filudi.com/v1/bundles/gloop/media/string')
    response.raise_for_status()
    # No body: the status says it all.
    ```

  </Fragment>
</CodePanel>

**Game media file, CDN origin for play.filudi.com (ADR 0007)**

Serves only final names (`<kind>-<format>-<sha256:16>.<ext>`). Answers a single `Range` with 206.

Credential: none. The route is public.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `slug` | path | string | yes |  |
| `file` | path | string | yes | pattern `^(image-(square\|landscape\|portrait)-[0-9a-f]{16}\.(avif\|webp\|jpg\|png)\|video-(landscape\|portrait)-[0-9a-f]{16}\.mp4)$` |
| `Range` | header | string | no |  |

### Responses

| Status | Body | Description |
| --- | --- | --- |
| 200 | none | File. Headers: `Cache-Control`, `Accept-Ranges`, `Cross-Origin-Resource-Policy`. |
| 206 | none | Requested byte range. |
| 404 | [Error](/docs/api/reference/schemas/#schema-error) | Unknown resource. |
| 416 | none | Range outside the file. |
