Tamper-proof image URLs with optional expiration.
Signed URLs
Signed URLs prevent unauthorized access to your transforms. When enabled, the CDN verifies an HMAC-SHA256 signature before processing any request.
How it works
- Your server generates a signature from the URL path + params + your secret
- The signature is appended as
s=parameter - The CDN verifies the signature before processing
# Unsigned
/project/photo.jpg?w=800&f=webp
# Signed
/project/photo.jpg?f=webp&w=800&s=a1b2c3d4e5f6...
Enable signing
Step 1: Generate a signing secret
curl -X POST https://app.spronta.com/api/images/projects/{id}/signing \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"enabled": true}'
# Response includes the secret (shown only once):
# { "signingSecret": "spronta_sign_abc123...", "enabled": true }
Step 2: Enforce signatures (optional)
By default, unsigned URLs still work even after enabling signing. To reject unsigned URLs:
curl -X POST https://app.spronta.com/api/images/projects/{id}/signing \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"requireSignedUrls": true}'
Generating signed URLs
Via API
curl -X PUT https://app.spronta.com/api/images/projects/{id}/signing \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"path": "/my-project/photo.jpg",
"params": {"w": "800", "f": "webp"},
"expiresIn": 3600
}'
# Response:
# { "url": "/my-project/photo.jpg?exp=1711036800&f=webp&w=800&s=...", "signature": "...", "expiresAt": 1711036800 }
Via SDK
import { Spronta } from "@spronta/images";
const spronta = new Spronta({
baseUrl: "https://cdn.spronta.com",
project: "my-project",
signingSecret: "spronta_sign_...",
});
// Signed URL (no expiration)
const url = await spronta.signedUrl("photo.jpg", { width: 800 });
// Signed URL with 1-hour expiration
const url = await spronta.signedUrl("photo.jpg", { width: 800 }, 3600);
Signature format
The signature is computed as:
HMAC-SHA256(secret, pathname + "?" + sorted_params)
- Params are sorted alphabetically
- The
sparam itself is excluded from the signing input - The
expparam (if present) is included in the signature - Output is lowercase hex
Expiration
Add expiresIn (seconds) when generating a signed URL. This adds an exp parameter with a Unix timestamp. The CDN rejects expired URLs before verifying the HMAC (fast path).
?exp=1711036800&w=800&s=... → valid until the timestamp