---
title: "Stream a GCS file directly to the caller"
method: GET
path: "/storage/download"
tags: ["Storage"]
---

# Stream a GCS file directly to the caller

`GET /storage/download`

Downloads a file from Google Cloud Storage and streams it as a binary response with a Content-Disposition: attachment header.

When to use: Use this endpoint when the caller can present API credentials and wants to receive file bytes in the HTTP response body. When the consumer cannot authenticate against this API (e.g. browser redirects, third-party delivery), use GET /storage/presigned-url instead, which returns a URL requiring no further authentication.

Preconditions: Requires a valid JWT. The filePath parameter must be a plain relative path (e.g. documents/report.pdf); the full GCS URI form (gs://bucket-name/...) is NOT accepted by this endpoint, unlike /storage/presigned-url. Paths are sanitized: values containing ../, leading slashes, backslashes, repeated slashes (//), or the characters <>:"|?* are rejected with 400. Multi-segment paths are also rejected with 400 when the first path segment contains a dot or is exactly "file" (e.g. reports.q1/data.csv, file/report.pdf).

The optional fileName parameter sets the filename in the Content-Disposition header. When omitted, the filename defaults to the last segment of filePath. The Content-Type header is inferred from the file extension; when the resolved name has no extension, a .csv extension is appended.

Response: A streaming binary body. Response headers include Content-Disposition: attachment; filename="<resolved-name>" and a Content-Type inferred from the file extension. No files are modified; this operation has no side effects.

## Query parameters

- `fileName` string
- `filePath` string, required

## Headers

- `tenant-id` string, required

## Response `200`

The requested file streamed as a binary attachment. Content-Disposition carries the resolved download filename and Content-Type is inferred from the file extension.

## Other responses

- `400` — The filePath was missing, malformed, or rejected by path sanitization (path traversal, leading slash, or illegal characters). Correct the path and retry.
- `401` — The request lacked a valid JWT. Authenticate and retry.
- `404` — No object exists at the resolved bucket and path. Verify the file was uploaded and the path is correct.
- `500` — The file download failed unexpectedly (e.g. a GCS read error). Retry; if the problem persists, contact support.

---

[API](https://skmtc.net/certifyos/apis/certify-api-layer.md) · [All operations](https://skmtc.net/certifyos/apis/certify-api-layer/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/certifyos/certify-api-layer/revisions/563848e0ecc0/schema)
