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.
/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
- Read the exact private object's metadata and retain its quoted
etag. - Upload the replacement to the same private key with that value in
If-Match. - 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.
| Client | Recommended integration |
|---|---|
| Main site / SquaredPoints visitors | Use public asset URLs directly. No Access credentials. |
| Human administrator | Use the same-origin admin portal, complete Cloudflare Access login, and let the portal call /admin/api/v1. |
| Trusted server or deployment job | Call /api/v1 with a dedicated Cloudflare Access Service Token and Service Auth policy. Keep both credentials server-side. |
| Untrusted browser code | Never embed service-token credentials or call the service API directly. |
Responses and safety
- Management responses are JSON and
private, no-store. - API v1 exposes only exact-object metadata and raw-body upload operations; there is no delete or bulk-write endpoint.
- Public keys beginning with
.well-known/,admin/,api/, ordocs/are reserved. - Direct
r2.devand R2 custom-domain access must stay disabled.