NextStorage Object Storage
Buckets, API keys, uploads, object URLs, and usage for NextStorage on NexHost.
NextStorage Object Storage#
NextStorage is Nexthomelabs' fourth product alongside NexHost, ProperInbox, and Nextsend: S3-style object storage for applications. Create buckets in the dashboard, generate a NextStorage API key, upload files through the NextStorage API, and serve them from your nexthomelabs.net object URLs. Every workspace starts with a 10 GB free quota.
What is NextStorage#
NextStorage gives every workspace:
- Buckets — logical containers similar to R2 or S3 buckets.
- Objects — files addressed by a path-like object key and a unique object UID.
- API keys —
nhs_live_…credentials for programmatic uploads. - Object URLs —
https://storage.nexthomelabs.net/o/:objectUiddelivery addresses. - Usage — stored bytes, bandwidth, requests, and object counts.
Creating a Bucket#
- Open NextStorage in the dashboard.
- Choose Create Bucket.
- Enter a bucket name and choose Private (default) or Public.
- Open the bucket to upload objects, browse by prefix, or change settings.
Buckets are isolated by workspace. Another workspace cannot list, read, or write your buckets.
Deleting a non-empty bucket requires explicit confirmation.
Endpoint#
The canonical Storage API lives on the dedicated storage host with no backend prefix:
https://storage.nexthomelabs.net/v1Object delivery uses the same host (/o/:objectUid and /b/:bucketUid/:objectKey). The older nexthomelabs.net/api/storage/v1 and nexthomelabs.net/storage/... paths keep working for backward compatibility.
API Authentication#
Every programmatic request uses a workspace API key:
Authorization: Bearer nhs_live_xxxxxxxxxxxxxxxxxxxxxGenerating an API Key#
- Open NextStorage, then API Access.
- Enter a key name and choose permissions.
- Choose Generate key.
- Copy the full key immediately — it is shown only once.
Available permissions:
storage:readstorage:writestorage:deletebuckets:readbuckets:write
Revoke a key at any time. Revoked keys stop working immediately.
Uploading Objects#
curl -X POST "https://storage.nexthomelabs.net/v1/buckets/my-assets/objects" \
-H "Authorization: Bearer nhs_live_CUSTOMER_API_KEY" \
-F "file=@./photo.jpg" \
-F "key=images/photo.jpg" \
-F "visibility=public"JavaScript:
const form = new FormData();
form.append('file', file);
form.append('key', 'products/gown.jpg');
form.append('visibility', 'public');
const response = await fetch('https://storage.nexthomelabs.net/v1/buckets/my-assets/objects', {
method: 'POST',
headers: {
Authorization: 'Bearer nhs_live_CUSTOMER_API_KEY'
},
body: form
});
const object = await response.json();
console.log(object.url);A successful upload returns:
{
"id": "obj_01K5DV7AXY0G6PPDX9M66ACZXQ",
"bucket": "my-assets",
"key": "products/gown.jpg",
"name": "gown.jpg",
"contentType": "image/jpeg",
"size": 428193,
"visibility": "public",
"status": "available",
"url": "https://storage.nexthomelabs.net/o/obj_01K5DV7AXY0G6PPDX9M66ACZXQ"
}Object Keys#
Object keys are path-like names:
photo.jpgavatars/user-48/avatar.pngproducts/gowns/gown-001.jpgvideos/promos/september.mp4documents/contracts/agreement.pdf
Keys support nested prefixes, unicode filenames, and folder-style listing with ?prefix=images/&search=photo. Path traversal (.., empty segments) is rejected. The object UID is independent from the object key.
Listing Objects#
curl "https://storage.nexthomelabs.net/v1/buckets/my-assets/objects?prefix=images/&limit=100" \
-H "Authorization: Bearer nhs_live_CUSTOMER_API_KEY"Retrieving Objects#
Every object has a stable UID URL:
https://storage.nexthomelabs.net/o/:objectUidBucket-style URLs use the globally unique bucket ID returned by the API:
https://storage.nexthomelabs.net/b/:bucketUid/:objectKeyClients stay on nexthomelabs.net. Delivery streams the object with the correct Content-Type, supports video range requests, and records bandwidth. Public images carry ETag/Last-Modified with browser and edge caching, so repeat <img> loads resolve to a fast 304 instead of a full download.
Public Buckets#
A public bucket is a bucket-wide grant: every current and future object can be opened through its NextStorage URL without authentication. Use this for a dedicated website-assets bucket where all files are intended for public delivery.
If the bucket is private, individual objects can still be made public from the Objects tab or through the API. This is the safer choice when only selected images, videos, or documents should be public.
curl -X PATCH "https://storage.nexthomelabs.net/v1/buckets/my-assets/objects/images/photo.jpg" \
-H "Authorization: Bearer nhs_live_CUSTOMER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"visibility":"public"}'Public URLs are delivery URLs, not API-only URLs. They return the real file with its stored Content-Type, so a public image can be used directly in frontend markup:
<img
src="https://storage.nexthomelabs.net/o/obj_01K5DV7AXY0G6PPDX9M66ACZXQ"
alt="Product photo"
>Do not place a NextStorage API key in browser code. Public delivery requires no key and includes cross-origin headers for websites and apps on other domains.
Private Buckets#
Private buckets are the default. A private object requires one of:
- A logged-in workspace session — open the same-origin URL (
/api/storage/o/:uid) in a
browser signed into the owning workspace. The dashboard preview does exactly this, so a private image in a private bucket renders for members with bucket access and for nobody else.
- A signed URL — mint
GET /storage/objects/:uid/signed-urlwhile logged in, then embed
the returned ?expires&sig URL in an <img> on any site. It is bound to that team, object, and expiry (default 15 minutes, max 24 hours) and needs no session or API key to render.
- A NextStorage API key with
storage:readscoped to the team/bucket (Authorization: Bearer nhs_live_…).
curl "https://nexthomelabs.com/api/storage/objects/obj_01K5DV7AXY0G6PPDX9M66ACZXQ/signed-url" \
-H "Cookie: nexhost_session=YOUR_SESSION"
# {"url":"https://storage.nexthomelabs.net/o/obj_…?expires=…&sig=…","expiresAt":"…"}<img src="https://storage.nexthomelabs.net/o/obj_01K5DV7AXY0G6PPDX9M66ACZXQ?expires=1757865600&sig=abc123" alt="Private product photo">Making a public bucket private locks every object in that bucket. Selected objects can then be published again individually. Unauthenticated requests to private objects receive a branded private file page during browser navigation and a machine-readable FORBIDDEN response for API requests.
Videos and large files#
Every video container is accepted (mp4, mov, webm, mkv, avi, and the rest) and single files may use the full 10 GB quota. Uploads are quota-gated, not format-gated: a 5 GB video succeeds while free quota remains and counts toward the 10 GB that unlocks paid storage. Keep the browser tab open until progress reaches 100% — large uploads stream to disk on the server and forward with an extended upstream timeout.
Two upload paths, different ceilings:
- Dashboard browser upload (same-origin
/api/storage/...) crosses the CDN and tops out
around 95 MB per file. Fine for images and short clips.
- Storage-host upload (
https://storage.nexthomelabs.net/v1/...with a NextStorage API key)
bypasses that CDN cap, so multi-GB videos succeed:
curl -X POST "https://storage.nexthomelabs.net/v1/buckets/my-assets/objects" \
-H "Authorization: Bearer nhs_live_CUSTOMER_API_KEY" \
-F "file=@./big-video.mkv" \
-F "key=videos/big-video.mkv" -F "visibility=private"Chunked/resumable browser uploads for multi-GB files are planned next; until then the API path above is the supported route for anything over ~95 MB.
Deleting Objects#
curl -X DELETE "https://storage.nexthomelabs.net/v1/buckets/my-assets/objects/images%2Fphoto.jpg" \
-H "Authorization: Bearer nhs_live_CUSTOMER_API_KEY"Encode / in object keys as %2F when calling key-addressed routes. Deletion updates bucket usage immediately.
Usage and Limits#
The dashboard shows buckets, objects, storage used, bandwidth used, and request counts. Uploads check workspace quota before contacting storage, and oversized uploads are rejected with STORAGE_QUOTA_EXCEEDED or UPLOAD_FAILED. The free tier is 10 GB per workspace with up to 25 buckets; single objects may be up to 10 GB.
Errors#
NextStorage returns its own error codes:
| Code | Meaning |
|---|---|
INVALID_API_KEY | The supplied NextStorage API key is invalid. |
BUCKET_NOT_FOUND | The requested NextStorage bucket was not found. |
OBJECT_NOT_FOUND | The requested NextStorage object was not found. |
STORAGE_QUOTA_EXCEEDED | Your NextStorage storage quota has been exceeded. |
UPLOAD_FAILED | NextStorage could not complete the upload. |
STORAGE_UNAVAILABLE | NextStorage is temporarily unable to access this object. |