betterpixels
Open Playground

Integration

soft launch

The headless serve API turns a saved preset into upscaled images of remote assets your app already serves. Two surfaces, never one URL: an authenticated trigger that spends a credit, and a public, content-addressed delivery URL that only ever returns precomputed bytes. Delivered from Cloudflare + R2.

Two surfaces

trigger authenticated · spends a credit
POST api.betterpixels.app/upscale

The only path that fetches a remote source and runs the GPU. Gated by a per-app secret, so only your app spends your credits. Takes the preset UUID + a source URL; returns the delivery URL.

delivery public · keyless · immutable
GET cdn.betterpixels.app/<content-hash>.webp

Returns only precomputed bytes, so a stranger hitting it can't spend credits. The key is hash(preset · source · options) — it leaks neither the preset name nor the origin. Cached forever on Cloudflare + R2.

The preset is referenced by its UUID (from the Presets screen), never its name — so renaming a preset never changes a URL or breaks your integration.

Quickstart

Trigger once from your backend, then serve the content URL it returns. The trigger returns immediately — render the URL right away and it shows the source until the upscale lands, then upgrades. Pass wait_ms to block until ready instead.

trigger.sh
# trigger an upscale (spends a credit; per-app secret)
curl -X POST https://api.betterpixels.app/upscale \
  -H "Authorization: Bearer bpx_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "preset": "9f3c2a1b-7d20-4e58-b6a1-0c4f2e9d1a77",
    "source": "https://render.guildwars2.com/file/7C08…/3690952.png"
  }'

# → { "url": "https://cdn.betterpixels.app/k7f3x9…q2.webp",
#     "status": "ready" }   // or "processing"
deliver.sh
# serve it — public, keyless, immutable
curl -I \
  https://cdn.betterpixels.app/k7f3x9…q2.webp

# ready    → 200, the upscaled bytes (cache-forever)
# in flight → 200, the original bytes (re-checks shortly)
# unknown  → 404 (the public path never triggers work)

App secrets

One secret per consuming app, scoped to you (the preset owner). The secret is the spend gate — it's what lets your app (and only your app) trigger credit-spending upscales, so no global origin allowlist is needed: your app vouches for its own sources. Pass it as Authorization: Bearer bpx_live_… on the trigger; the public delivery URL needs no secret.

Sign in to create and manage app secrets.

Sign in

Cloudflare Worker

Keep your existing asset URLs for clients: a Worker triggers the upscale on first request and redirects to the content URL the trigger returns.

worker.js
export default {
  async fetch(req, env) {
    // resolve once on your backend, then cache the mapping
    const { url } = await (await fetch(
      "https://api.betterpixels.app/upscale", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${env.BPX_SECRET}`,
        },
        body: JSON.stringify({ preset: env.PRESET_ID, source: req.url }),
      })).json();
    return Response.redirect(url, 302);
  }
}

Serve-time fallback

The delivery URL never shows a broken image. While an upscale is in flight it serves the original bytes (short cache, so the edge re-checks); once ready it upgrades to the upscaled result and caches it forever. A page can render the content URL immediately and it simply sharpens when the work completes.

readyupscaled bytes · cache-forever, immutable
processingoriginal bytes · short cache (upgrades on re-check)
never triggered404 · the public path never spends a credit