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

  1. Your server generates a signature from the URL path + params + your secret
  2. The signature is appended as s= parameter
  3. 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 s param itself is excluded from the signing input
  • The exp param (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