Skip to content

Signed URLs

Last updated 9 Nov 2026

A signed URL lets a browser or app read a private file, upload a file or load a resized image without holding your keys. Your server creates the URL, and it stops working after the expiry time.

Hostname Signed URL Expiry
<space>.vault Always Required
<space>.upload Always Required
<space>.edge with image parameters Always Not used
<space>.edge without parameters Not needed Not used
https://k3x9q2m7.vault.binedge.net/production/tickets/screenshot.png
?exp=1798765200&sig=<signature>

exp is a Unix time in seconds (UTC). The URL works while the current time is before it. sig is an HMAC-SHA256 of the hostname role, your space name, the object key and the other parameters, encoded as base64url.

Storage::disk('binedge')
->temporaryUrl('tickets/screenshot.png', now()->addMinutes(10));

The disk adds your environment prefix (production/ or dev/) to the path, so the signed key is production/tickets/screenshot.png. Upload URLs come from temporaryUploadUrl() and resized image URLs from imageUrl(), see Uploads and Image resizing.

Join these five lines with a line feed (0x0A), with no line feed after the last one:

BINEDGE-HMAC-SHA256
<role>
<space>
<object key>
<canonical query>
  • <role> is vault, upload or edge, the second label of the hostname.
  • <object key> is the path without the leading /, decoded once, as UTF-8. %2F becomes /; + stays +.
  • <canonical query> takes every parameter except sig, encodes each name and value as in RFC 3986 (A-Z a-z 0-9 - . _ ~ stay as they are, every other byte becomes upper-case %XX), sorts them by encoded name, and joins them as name=value with &. With no parameters the line is empty.
  • sig is the HMAC-SHA256 of the string with your signing key, encoded as base64url without = padding.

The first part of the object key chooses the key, not the request:

Key starts with Signing key
production/ or shared/ Your production signing key
dev/ Your development signing key
Anything else Rejected with key_scope_unknown

Your development servers only hold the development key, so they cannot sign URLs under production/.

These examples use the space k3x9q2m7 and the test key binedge-test-production-key. Your code should produce the same string to sign and the same sig.

A private file whose key has a space and Chinese characters:

BINEDGE-HMAC-SHA256
vault
k3x9q2m7
production/tickets/截图 1.png
exp=1798765200
https://k3x9q2m7.vault.binedge.net/production/tickets/%E6%88%AA%E5%9B%BE%201.png?exp=1798765200&sig=OwicRpmPadfNbMpoA6zAMjfMR1pxvVyUY6b2vLQlCOk

An upload that accepts PNG and JPEG up to 10 MiB. The / and , in types are encoded in the string to sign:

BINEDGE-HMAC-SHA256
upload
k3x9q2m7
production/support-uploads/staging/7/b.jpg
exp=1798765200&max_bytes=10485760&types=image%2Fpng%2Cimage%2Fjpeg
https://k3x9q2m7.upload.binedge.net/production/support-uploads/staging/7/b.jpg?exp=1798765200&max_bytes=10485760&types=image%2Fpng%2Cimage%2Fjpeg&sig=nppbmNIXVrRWiR4ZPWQe9MYUuJSDUNpQ1wGN2oLf1mA

A resized public image. The parameters are sorted by name, and edge URLs have no exp:

BINEDGE-HMAC-SHA256
edge
k3x9q2m7
production/groups/logo.png
crop=smart&fit=cover&fmt=webp&h=144&q=75&w=144
https://k3x9q2m7.edge.binedge.net/production/groups/logo.png?crop=smart&fit=cover&fmt=webp&h=144&q=75&w=144&sig=410RAzVg42KRbH5gEBlzbrYq5d7w-5avYm4J2EA9kro
Reason Meaning
signature_missing The URL has no sig
signature_invalid sig does not match the URL
signature_expired The expiry time has passed
key_scope_unknown The key does not start with production/, shared/ or dev/

All four return HTTP 403 with the reason in the error body. On edge and vault a visitor’s browser is then sent to the binedge.net error page, see Delivery URLs; upload returns the body as it is:

{"error":{"class":"permission_denied","message":"调用方无权访问该目标或能力。","retryable":false,"platform_code":null,"platform_message":null,"operation_id":null,"reason":"signature_expired"}}

Branch on reason, not on message.