Skip to main content

Download artifact from private bucket

Artifacts of a private app live in the private bucket and are never served by a public URL. Their links point to the API instead — {API_URL}/download?key=<key> — and this endpoint decides whether the caller may have the file. If so, it answers with a short-lived signed URL.

Access is decided per app, by its download_mode, which is set on create and can be changed on update.

Endpoint​

GET /download

Authentication​

The endpoint is public; access depends on the app's download_mode and on the credential sent with the request.

HeaderValueRequired
X-Download-Tokenfnd_… download token of the app and channelConditional
AuthorizationBearer <jwt_token>Conditional
download_modeWho gets the file
unlistedAnyone who knows the key.
strictA request with the download token of the artifact's app and channel, or a JWT of the owning admin or of a team user with the download permission and access to the app and channel.

A JWT with access works in both modes. CI/CD tokens (fns_…) are not accepted on this endpoint.

Query Parameters​

ParameterTypeRequiredDescription
keystring✅URL-encoded object key from the artifact link

Example Requests​

With a download token (strict app)​

curl -X GET --location 'http://localhost:9000/download?key=secondapp-admin%2Fstable%2Flinux%2Famd64%2Fsecondapp-0.0.1.deb' \
--header 'X-Download-Token: fnd_<token>'

With a JWT​

curl -X GET 'http://localhost:9000/download?key=secondapp-admin%2Fstable%2Flinux%2Famd64%2Fsecondapp-0.0.1.deb' \
--header 'Authorization: Bearer <jwt_token>'

Response​

Download token, or unlisted app (302 Found)​

The response redirects to the signed URL of the file.

JWT with access (200 OK)​

{
"download_url": "https://<bucket_name>.s3.amazonaws.com/secondapp-admin/stable/linux/amd64/secondapp-0.0.1.deb?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=MdnaDEXKy9nOc4beIvNcgy%2F20250409%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250409T153628Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=bb89a695151c19880c2a2de6620e49a8f532ef1b356542f4821e701c32db9382"
}

Denied or unknown key (404 Not Found)​

{
"error": "Artifact not found"
}

A denied request gets exactly the same answer as a key that does not exist, so the endpoint cannot be used to find out which private artifacts exist.

Response Fields​

FieldTypeDescription
download_urlstringSigned URL for downloading the file (JWT requests only)

Notes​

  • The signed URL expires after 15 minutes
  • URL encoding is required for the key parameter
  • Only keys of artifacts that belong to a private app resolve; any other key returns 404
  • A download token is scoped to one app and one channel: a token for beta does not open an artifact in stable
  • Clients of a strict app must send the same header on update checks too, not only on /download
  • If your HTTP client follows the redirect, do not forward X-Download-Token to the storage host
  • ENABLE_PRIVATE_APP_DOWNLOADING no longer controls this endpoint; it only sets the default download_mode for new private apps (see environment variables)