Immich
A transparent reverse proxy in front of Immich meters shared-link photo resolves — a per-resolve license fee.
What gets metered
an external shared-link asset resolve — the proxy passes every request through to Immich and, when a shared-link asset is fetched (GET /api/assets/:id/original?key=…), looks up the asset's owner and reports a per-resolve license fee.
- Who pays: the resolving agent/downloader — an
x-resolver-idheader, falling back to the share key (mapped inPAYER_WALLETS) - Who gets paid: the asset owner — the EXIF artist when present, else Immich's
ownerId(mapped inCREATOR_WALLETS)
Attach surface — no fork
The HTTP boundary: createImmichProxy sits in front of Immich and proxies everything. Zero Immich edit — point your share URLs / clients at the proxy instead of Immich directly.
Quickstart
Run the metering proxy in front of your Immich instance:
PLATFORM=immich-proxy UPSTREAM_URL=http://immich:2283 RATE=25000 \
PAYER_WALLETS='{"<resolverId>":"0x…"}' \
CREATOR_WALLETS='{"<ownerId-or-exif-artist>":"0x…"}' \
FACILITATOR_URL=https://facilitator.example FACILITATOR_API_KEY=… \
npx up-integration # RATE = micro-USDC per resolve
# point share URLs / clients at the proxy instead of Immich directly
All values above are placeholders — supply your own facilitator, wallets, and rate.
The shared prerequisites (a deployed StakeVaultFactory, a running
facilitator, a wallet registry) are covered in the admin overview.
Verify
node scripts/e2e-immich-live-docker.mjs Full loop against a live Immich (server + vectorchord postgres + redis): upload a photo, create a shared link, resolve it through the proxy — the real image bytes stream through (200) and the license fee settles on anvil.
Notes & caveats
Links
- Recipe:
packages/integrations/deploy/immich/README.md— the authoritative attach instructions in the repo. - Testing plan — Immich row
- Integration Playbook — how integrations like this one are built.
- Testing plan — this platform's row in the L1→L4 matrix.