Zero cloud setup
No AWS IAM, bucket policies, or CORS headaches. One clean API key and you're live in 30 seconds.
Stop wasting weekends configuring AWS S3, CloudFront distributions, Lambda resize workers, and IAM permissions.
Upload any image once. ROC automatically optimizes it, fixes sideways phone uploads, strips private data, and lets you resize it right in the URL. Built for solo developers, agencies, and e-commerce stores.
No AWS IAM, bucket policies, or CORS headaches. One clean API key and you're live in 30 seconds.
?w=300&h=300
Need a new avatar size or product crop? Change the URL query parameter. Never re-process files or touch the database.
We store a single WebP master, not 5 duplicate files. Your storage plan stretches further with zero wasted space.
Whether it's a 15 MB DSLR photo or a messy smartphone screenshot, ROC makes it web-ready before returning your URL.
Accepts JPEG, PNG, WebP & AVIF. Blocks corrupted uploads before anything touches storage.
Detects phone camera rotation so user uploads never show up sideways on your site.
Strips hidden camera EXIF data and private GPS location before publishing.
Compresses into a single WebP master. Raw 10 MB camera files shrink to ~300 KB with zero visible loss.
Replacing an avatar or banner? The old image stays live until the new one is safely written, so uploads never break.
No arbitrary asset counter. You are only billed for actual bytes on disk, so you can upload thousands of images freely.
Every image is served with 1-year immutable caching and instant 304 revalidation for lightning-fast page speeds.
Change image dimensions, aspect ratios, or formats right where you write your HTML or CSS.
wh
Width and height in pixels (1 to 3840px)
fit
cover, contain, inside or fill for responsive crops
q
Quality tuning (1 to 100) to optimize mobile file weight
format
jpg, png, or webp for legacy clients and emails
# master roc.phyr.in/:appId/:assetId # thumbnail roc.phyr.in/:appId/:assetId?w=320&h=320 # square avatar roc.phyr.in/:appId/:assetId?w=120&h=120&fit=cover&q=80 # JPEG for email roc.phyr.in/:appId/:assetId.jpg
Need a 120px round avatar or a 400px product card? Pass it in the URL. Stored files remain completely untouched.
Deliver lightweight thumbnails to mobile shoppers instead of downloading heavy full-resolution hero photos.
Each custom width, crop, and format combination is cached at the edge for instant subsequent page loads.
Whether you are shipping a solo side project, running client sites, or scaling an online store.
You’re building a product, not an infrastructure company. Don't waste your weekend writing Lambda triggers, configuring S3 buckets, and debugging CORS errors. Upload with one POST request, get a CDN URL, and get back to shipping features.
?w= and ?h=Non-technical clients always upload 15 MB uncompressed photos straight from their phone, wrecking page speed and layout grids. ROC automatically compresses, rotates, and serves every client upload so client sites stay blazing fast on Google Lighthouse.
Heavy, slow product images kill mobile conversions. With ROC, one product photo powers your entire store: use uniform square crops for catalog grids, high-res zoom for product detail pages, and lightweight thumbnails for cart sliders.
fit=coverImprove Core Web Vitals, reduce bounce rates, and improve SEO rankings without pulling backend engineers away from your product roadmap. ROC delivers production-ready image infrastructure with flat yearly pricing.
GET /api/v1/usage
Many email clients (like Outlook) still don't render modern WebP. Simply
append .jpg or ?format=jpg to any asset URL for instant
on-the-fly JPEG delivery. For mobile apps, private user GPS location data
is automatically stripped on upload.
.jpgS3 and R2 are raw object buckets built for generic data. ROC is a purpose-built image engine that saves you days of DevOps engineering.
| ROC | AWS S3 | Cloudflare R2 | |
|---|---|---|---|
| Setup Time | 30 seconds (1 API key) | Hours (IAM, Bucket policies, CORS) | Complex (Tokens, buckets, workers) |
| Image Resizing | Instant via URL (?w=300) | Write & maintain Lambda@Edge | Requires separate paid add-on |
| Format Optimization | Automatic WebP, JPEG, PNG | Build your own Sharp pipeline | Requires custom worker scripts |
| Client Upload Protection | Auto-orient, compress & strip EXIF | None (Stores raw 15 MB files as-is) | None (Stores raw 15 MB files as-is) |
| Billing Predictability | Flat yearly plan (Zero surprise bills) | Complex multi-metered billing | Egress + operation math |
| Best for | Solo devs, agencies & e-commerce | General enterprise cloud backups | Large-scale unstructured objects |
Flat storage quota in GB. No surprise bandwidth fees, no per-transformation charges, no egress tax.
Side projects and early products
Production apps
Image-heavy products
REST over HTTPS, no SDK. Uploads, replaces, deletes and usage reads
need an x-api-key header. Delivery URLs are public.
/api/v1/assets
Upload an image as multipart/form-data in the
file field.
/api/v1/assets/replace
Pass image url (or assetId) and a new file.
The old file is removed only after the new one is saved.
/api/v1/assets
Delete by image ?url=... or :assetId.
Removes stored files and reclaims quota immediately.
/api/v1/usage
Returns live storage used, quota limit, plan details and active assets.
/:applicationId/:assetId
Public delivery. Add ?w=, &h=,
&fit= and &q= to transform, or
.jpg / ?format=jpg to convert.
curl -X POST https://roc.phyr.in/api/v1/assets \ -H "x-api-key: YOUR_API_KEY" \ -F "file=@/path/to/picture.jpg" # response { "success": true, "data": { "assetId": "39a1d82f7c01b4e2", "url": ".../39a1d82f7c01b4e2" } } # check storage and plan curl https://roc.phyr.in/api/v1/usage \ -H "x-api-key: YOUR_API_KEY"
const formData = new FormData(); formData.append('file', fileBlob, 'photo.png'); const res = await fetch( 'https://roc.phyr.in/api/v1/assets', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY' }, body: formData }); const { data } = await res.json(); // any size, from the same master const avatar = data.url + '?w=120&h=120&fit=cover&q=80';
import requests res = requests.post( "https://roc.phyr.in/api/v1/assets", headers={"x-api-key": "YOUR_API_KEY"}, files={"file": open("picture.jpg", "rb")}, ) url = res.json()["data"]["url"] # any size, from the same master thumb = url + "?w=320&h=320" usage = requests.get( "https://roc.phyr.in/api/v1/usage", headers={"x-api-key": "YOUR_API_KEY"}, ).json()
<!-- master --> <img src="https://roc.phyr.in/:appId/:assetId" alt=""> <!-- dynamic thumbnail --> <img src="https://roc.phyr.in/:appId/:assetId?w=320&h=320" width="320" height="320" alt=""> <!-- avatar crop --> <img src="https://roc.phyr.in/:appId/:assetId?w=120&h=120&fit=cover&q=80" width="120" height="120" alt=""> <!-- legacy email client --> <img src="https://roc.phyr.in/:appId/:assetId.jpg" alt="">
# master GET /:appId/:assetId # dynamic thumbnail GET /:appId/:assetId?w=320&h=320 # avatar crop GET /:appId/:assetId?w=120&h=120&fit=cover&q=80 # legacy email / JPEG GET /:appId/:assetId.jpg GET /:appId/:assetId?format=jpg HTTP/1.1 200 OK Cache-Control: public, max-age=31536000, immutable ETag: "<one per w, h, q, fit, format>"
S3 and R2 are raw storage buckets. To make them work for a modern web app or store, you have to configure IAM permissions, bucket policies, CloudFront distributions, and maintain serverless Lambda functions to resize images. ROC gives you a complete, ready-to-use image backend: upload with one API key, get automated WebP compression, phone photo auto-rotation, private GPS stripping, and on-demand URL resizing with zero cloud DevOps.
Upload your image once. When rendering it in your app, website, or newsletter,
simply append query parameters like ?w=320&h=320&fit=cover
to the URL. ROC transforms the image on the fly, applies immutable edge caching,
and streams the optimized asset instantly.
ROC handles them automatically. It corrects camera rotation, strips heavy metadata, and compresses the photo into a featherlight WebP master (~200–400 KB). Your website or app never slows down from raw user uploads.
Simply append .jpg or ?format=jpg to any asset URL.
ROC converts and streams a high-quality JPEG in memory with the same long-lived
caching headers.
By total storage on disk (in GB). You are never penalized for uploading thousands of small images or thumbnails; you only pay for actual bytes stored.
Yes. The atomic replace endpoint verifies and saves the new image before retiring the old one. If an upload fails midway, your current live image remains safely in place.