CDN

CDN

Oblien's CDN stores and delivers your assets (images and files), generating image variants on demand and serving them from your account's edge host — optionally on your own domain.

In one line — your backend mints a short-lived upload permit, your client uploads straight to your account's CDN host with it, and the CDN records the upload back to Oblien. Files serve from your account host; namespace is an API-side tag for quota, sorting and listing. New here? Read How it works first.

At a glance

CapabilitySummary
Per-account hostYour account serves from one <slug>.cdn.oblien.com (or a custom domain), shared across all your namespaces. See How it works.
NamespacesAn API-side tag on each upload — organize, filter, and quota. Not a host, never in a URL.
UploadsClient uploads with a one-shot permit; CDN returns URLs + a recorded confirmation. See Uploads.
VariantsThumbnails/resizes/re-encodes chosen per request via the permit's variants object — no server presets, default none.
Custom domainsServe from cdn.yourbrand.com (account-level) via the /cdn/domains API (DNS + auto TLS). See Custom domains.
QuotasPer-namespace storage + monthly-ingest caps, enforced at token mint. See Quotas.
Auto-deleteMark an upload to expire after a TTL; the node reclaims it. See Auto-delete.
Traffic & suspendDelivery egress is metered and billed per account; over-limit accounts are suspended. See Traffic & billing.
Usage & statsPer-namespace usage, windowed series, quotas and files. See Usage & stats.

Quick start

import Oblien from 'oblien';
import { readFileSync } from 'node:fs';

const oblien = new Oblien({
  clientId: process.env.OBLIEN_CLIENT_ID!,
  clientSecret: process.env.OBLIEN_CLIENT_SECRET!,
});

// Server-side one-shot: mints a permit + uploads, scoped to a namespace.
const { url, variants } = await oblien.cdn.upload(
  { data: readFileSync('./logo.png'), filename: 'logo.png', contentType: 'image/png' },
  { namespace: 'customer-123' },
);
// url → https://<slug>.cdn.oblien.com/static/ab/cd/logo.png
# 1. Backend mints a permit (scoped to a namespace)
POST /cdn/token
X-Client-ID: <id>
X-Client-Secret: <secret>
{ "namespace": "customer-123" }
# → { "token": "<permit>", ... }

# 2. Client uploads to your account host with the permit
POST https://<slug>.cdn.oblien.com/api
Authorization: Bearer <permit>
Content-Type: multipart/form-data   (field: "file")
# → { "url": "https://<slug>.cdn.oblien.com/static/…", "variants": [...], "recorded": true }
# 1. Backend mints a permit
TOKEN=$(curl -s -X POST https://api.oblien.com/cdn/token \
  -H "X-Client-ID: $OBLIEN_CLIENT_ID" -H "X-Client-Secret: $OBLIEN_CLIENT_SECRET" \
  -H "Content-Type: application/json" -d '{"namespace":"customer-123"}' | jq -r .token)

# 2. Client uploads with the permit (host from the mint/your backend)
curl -X POST "https://$CDN_HOST/api" \
  -H "Authorization: Bearer $TOKEN" -F "file=@./logo.png"

Read How it works for the account-host + namespace-tag model and the backend-vs-client split, then the upload contract for request/response shapes, per-request variants, and single-use permit semantics.