Mint Signed URLs

Mint download URLs for every file in the artifact.

Signing is all-or-nothing: every file in storage_objects is covered in a single batch with a shared expires_at. Every successful call appears in List Signed URL Audit.

See the Artifacts overview for consumption recipes (DuckDB, GeoPandas, QGIS).

The requested lifetime picks the mechanism

The lifetime you ask for decides what kind of URL you get back. There is no separate endpoint or flag — just the TTL.

Requested lifetimeWhat you getLives in
≤ 7 days (604 800s)A time-limited signed URL per file, plus links.dashboard_url. Not stored anywhere — once expired it cannot be replayed.Nothing persisted
> 7 days, up to 180 daysA persistent download link: one durable, revocable URL per file. Each hit re-issues a fresh short-lived URL behind the scenes, so the link keeps working for its whole lifetime, plus a links.dashboard_url tied to that link.A managed link you can retune or revoke

7 days is the hard ceiling for a signed URL, so anything longer is served by the persistent-link mechanism instead. Persistent links are the ones you can retune or revoke, and they appear in the list endpoint as artifact_download_link rows.

A download link is a bearer credential. Anyone holding the URL can download the artifact without authenticating, until it expires or you revoke it. Share it deliberately, and revoke it if it leaks.

Use cases

  • Hand off the bundle to a BI tool that reads HTTPS-served parquet directly (DuckDB httpfs, GeoPandas, QGIS) — a short TTL is enough.
  • Give a colleague or auditor a link that still works weeks later — request a lifetime beyond 7 days and share the persistent URL.
  • Open dashboard_url to inspect the artifact in Epoch's dashboard without minting your own URLs.

Path parameters

ParamTypeDescription
iduuidArtifact ID. Must be visible to your organization and in the completed state.

Request body

The body is optional — a request with no body (or {}) uses the default TTL. Give the lifetime either as an absolute deadline or as a relative window; supplying both is rejected.

FieldTypeRequiredDescription
expires_atISO 8601noAbsolute expiry, and the preferred form — you state the deadline rather than computing a window against Epoch's clock. Must be in the future and no more than 180 days out. Mutually exclusive with ttl_seconds.
ttl_secondsintnoLifetime in seconds, relative to now. Between 1 and 15 552 000 (180 days). Defaults to 3 600 (1 hour). Mutually exclusive with expires_at.

Every URL in files[] shares the same expires_at regardless of which form you use.

Response schema (data)

FieldTypeDescription
type"artifact_signed_urls"Always "artifact_signed_urls".
iduuidArtifact ID these URLs cover.

attributes

FieldTypeDescription
ttl_secondsintThe lifetime applied to every URL in files[].
expires_atISO 8601Absolute expiry. Identical for every entry in files[].
filesarrayOne entry per file in the artifact's storage_objects. Single-file artifacts return exactly one entry; partitioned artifacts return one per file. Always iterate this array — there is no top-level signed_url field.

files[]

FieldTypeDescription
relative_pathstringIdentifies which file in storage_objects this URL belongs to.
signed_urlstringThe download URL. For a short-lived request this is a direct storage URL; for a persistent link it is a durable Epoch URL that redirects to freshly-issued storage URLs on each hit. Either way, it stops working at expires_at.
KeyTypeDescription
selfstring (URL)This endpoint.
dashboard_urlstring (URL)Deep link that opens this artifact in Epoch's dashboard. Expires at expires_at. For a persistent link it is tied to that link, so revoking the link closes the dashboard too.

The persistent URL contains a token that identifies the link. Pass that token to Retune Download Link to change the expiry, or Revoke Download Link to kill it. The token is returned only once, here — Epoch stores only a hash of it, so keep the URL if you intend to manage the link later. If you lose it, revoke the link by listing it and mint a fresh one.

Status codes

  • 200 — Success. Every file in the artifact is covered.
  • 400 — Invalid id (not a UUID); ttl_seconds out of range; expires_at in the past or more than 180 days out; or both lifetime fields supplied at once.
  • 401 — Missing or invalid API key.
  • 403 — Caller lacks the artifacts:sign scope.
  • 404 — Artifact does not exist or is not visible to your organization.
  • 409 — artifact_not_completed: the artifact is not yet in the completed state. Download URLs are only available for completed artifacts.
  • 409 — artifact_purged: the artifact completed, but its files have aged out of retention (status: "purged"). Nothing can be minted for it — request a new artifact with the same filters. The response names the purged_at date.

Required scope: artifacts:sign

artifacts:sign is intentionally separate from artifacts:write. A key that can read or generate artifacts does not implicitly receive the ability to mint download URLs.