file_url()

Return a public, signed URL that downloads a stored file (from a file field) with no login. Use it to hand a file to an external system that fetches by URL, or as an <img src> in a generated PDF.

Syntax

file_url(file, opts?)

Parameters

Name Type Required Description
file object | array yes A file object {name, path, type, size, host}, or a whole file-field value (an array — the first file is used).
opts array no ttl — seconds until the URL expires (default 3600, one hour). permanenttrue for a URL that never expires.

Returns

An absolute https://…/filedl/… URL. Throws if the value isn't a file or the file doesn't belong to your workspace.

Examples

// Default: a link that works for one hour
$url = file_url($record["contract"][0]);

// Custom lifetime — 24 hours
$url = file_url($record["contract"][0], ["ttl" => 86400]);

// Never expires
$url = file_url($record["logo"][0], ["permanent" => true]);

// Send a file to an external API that fetches by URL
curl_post_json("https://api.example.com/import", [
    "document_url" => file_url($record["contract"][0], ["ttl" => 600])
]);

⚠️ Security — read this

A signed URL is a bearer capability: anyone who has the link can download the file until it expires — there is no further login or permission check. The link isn't guessable (it's cryptographically signed), but treat it like a password.

  • Prefer a short ttl. Only use permanent when a link genuinely must live forever.
  • Permanent links can't be individually revoked. The only way to invalidate outstanding URLs is a system-wide secret rotation (which breaks all file URLs at once) — contact support if you ever need this.
  • Deleting the file does not immediately kill its URL. A link points at the file's stored copy; on managed storage that copy is retained for ~30 days before cleanup (and indefinitely on bring-your-own storage), so an unexpired link can keep serving the old file during that window. Re-uploading a file creates a new link — the old one never serves the new file.

Notes

  • File fields are arrays$record["doc"][0] is the first file; passing the whole array uses the first.
  • The URL streams the file's original bytes (no size cap, unlike file_base64()).
  • For embedding an image in a PDF you can use this or file_data_uri(); the data URI embeds the bytes directly (no network fetch), while file_url has mpdf fetch the image at render time.

See also: file_base64(), file_data_uri()