RSquared Studios developer documentation

Assets CDN and API

Public media is available at stable, clean URLs. Trusted service clients manage exact objects through the versioned /api/v1 API.

Authentication boundary: the human admin portal uses Cloudflare Access and calls the same API through its same-origin /admin/api/v1 wrapper. Automated clients use /api/v1 with a dedicated Cloudflare Access Service Token. Keep its secret on a trusted server; never place it in browser JavaScript. Public asset reads and this documentation do not require login.

Public asset delivery

Store a main-site object as public/site/brand/logo.a1b2c3.png; the site uses it as:

<img src="https://assets.rsquaredstudios.net/site/brand/logo.a1b2c3.png" alt="RSquared Studios">

Images, audio, video, and fonts are allowlisted. Responses support ETags, conditional requests, HEAD, and single video byte ranges. Use content-hashed filenames: query strings are ignored for object and cache identity.

Service API

Inspect one object

GET /api/v1/assets/{visibility}/{key}

Returns metadata and the canonical delivery URL. HEAD returns metadata headers without a body.

Upload one object

PUT /api/v1/assets/{visibility}/{key}

Streams the raw request body to storage with an explicit write precondition.

Create a public asset from a trusted service

curl --request PUT "https://assets.rsquaredstudios.net/api/v1/assets/public/site/brand/logo.a1b2c3.png" \
  --header "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
  --header "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET" \
  --header "Content-Type: image/png" \
  --header "If-None-Match: *" \
  --data-binary "@logo.png"

Public uploads are always create-only and require If-None-Match: *. Existing public objects cannot be replaced through API v1; publish a new content-hashed key instead. Uploads must include Content-Length and an allowlisted content type. The configured Worker limit is 90 MiB and may also be capped by the Cloudflare account plan.

Read exact-object metadata

curl "https://assets.rsquaredstudios.net/api/v1/assets/public/site/brand/logo.a1b2c3.png" \
  --header "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
  --header "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET"

Metadata lookup requires the complete visibility and key. Use HEAD when only response headers are needed.

Conditionally replace a private asset

  1. Read the exact private object's metadata and retain its quoted etag.
  2. Upload the replacement to the same private key with that value in If-Match.
  3. If the API returns 412, re-read metadata instead of blindly retrying.

Create a new private object with If-None-Match: *. If-Match replacement is accepted only for private assets.

Integration rules

Give the main site and SquaredPoints separate service tokens and non-overlapping prefixes such as site/ and squaredpoints/. The Worker checks the verified token identity against its configured prefixes on every API request.

ClientRecommended integration
Main site / SquaredPoints visitorsUse public asset URLs directly. No Access credentials.
Human administratorUse the same-origin admin portal, complete Cloudflare Access login, and let the portal call /admin/api/v1.
Trusted server or deployment jobCall /api/v1 with a dedicated Cloudflare Access Service Token and Service Auth policy. Keep both credentials server-side.
Untrusted browser codeNever embed service-token credentials or call the service API directly.

Responses and safety

OpenAPI 3.1 specification for API v1