Get started

AlzCloud API

Programmatic file storage — upload, download, embed and stream, available on Starter and Pro. Manage keys under My Apps.

Base URL: https://cloud.alz.name.ng/api/v1

Authentication

Each API app you create has its own key. Pass it as a header:

X-API-Key: your_app_key

Or as a query param (less secure, useful for quick testing in a browser):

GET /api/v1/files?api_key=your_app_key

Files, storage and webhooks are all scoped to the calling app's key — one app never sees another app's data, even on the same account.

Error codes

CodeMeaning
401Missing, invalid, or revoked API key
403API access not on your plan, or a quota reached
404File / webhook / app not found
400Bad request (missing fields, file too large)
415File type can't be embedded
429Rate limited — slow down (300 requests / 15 min per key)
500Server error — try again later

Status

GET/api/v1/statusPublic, no auth — health/version check
{ "status": "ok", "version": "v1", "time": "2026-07-11T12:00:00.000Z" }

Account info

GET/api/v1/meYour account + plan details
curl https://cloud.alz.name.ng/api/v1/me \
  -H "X-API-Key: your_app_key"
{
  "id": 1,
  "username": "yourname",
  "plan": "starter",
  "api_app": "My Mobile App",
  "storage_used_human": "10 MB",
  "storage_limit_human": "100 GB"
}

API usage (this app)

Call volume for the key you're using — separate from account storage. Useful for watching your own rate-limit headroom.

GET/api/v1/usageRequests in the last 15m / 24h / this month
{
  "api_app": "My Mobile App",
  "requests_last_15m": 12,
  "rate_limit_window": "15m",
  "rate_limit_max": 300,
  "requests_last_24h": 340,
  "requests_this_month": 5210
}

Storage usage

Account-level — shared across every app you own plus the dashboard.

GET/api/v1/storageStorage breakdown
{
  "used_human": "10 MB",
  "limit_human": "100 GB",
  "remaining_human": "99.9 GB",
  "percent": 0
}

List files

Scoped to the calling app's key — you'll only see files this specific app uploaded, not other apps on your account or your dashboard uploads.

GET/api/v1/filesList files uploaded by this app's key
ParamDefault
limit20 (max 100)
offset0
{
  "files": [{
    "name": "video.mp4",
    "slug": "abc123def456",
    "size_human": "50 MB",
    "file_type": "video",
    "is_public": true,
    "url": "https://cloud.alz.name.ng/f/abc123def456",
    "download_url": "https://cloud.alz.name.ng/api/you/your-app/abc123def456/video.mp4?download=1",
    "stream_url": "https://cloud.alz.name.ng/api/you/your-app/abc123def456/video.mp4",
    "embed_url": "https://cloud.alz.name.ng/embed/abc123def456",
    "embed_code": "<iframe src=\"https://cloud.alz.name.ng/embed/abc123def456\" width=\"100%\" height=\"360\" frameborder=\"0\" allowfullscreen></iframe>"
  }],
  "total": 42, "limit": 20, "offset": 0
}

Every file response already includes a ready-to-paste embed_code — copy it straight into a page, no extra assembly needed. See Embed & sizes below.

Upload file

POST/api/v1/uploadmultipart/form-data, field "file"
curl -X POST https://cloud.alz.name.ng/api/v1/upload \
  -H "X-API-Key: your_app_key" \
  -F "file=@/path/to/video.mp4"
// Works directly from browser JS too — CORS is open on /api/v1,
// so a visitor's browser can upload straight to AlzCloud without
// round-tripping through your own backend.
const form = new FormData();
form.append('file', fileBlob, 'myfile.mp4');
const res = await fetch('https://cloud.alz.name.ng/api/v1/upload', {
  method: 'POST',
  headers: { 'X-API-Key': 'your_app_key' },
  body: form,
});
const data = await res.json();
// data.embed_code is ready to insert into the page right away

Update file

Rename a file and/or toggle its public visibility. Send only the fields you want to change.

PATCH/api/v1/files/:slug
curl -X PATCH https://cloud.alz.name.ng/api/v1/files/abc123def456 \
  -H "X-API-Key: your_app_key" \
  -H "Content-Type: application/json" \
  -d '{"name": "renamed.mp4", "is_public": false}'

Delete file

DELETE/api/v1/files/:slug
curl -X DELETE https://cloud.alz.name.ng/api/v1/files/abc123def456 \
  -H "X-API-Key: your_app_key"

Batch delete

Delete up to 100 files in one call. Partial failures don't abort the batch — check failed in the response.

DELETE/api/v1/filesBody: { "slugs": [...] }
curl -X DELETE https://cloud.alz.name.ng/api/v1/files \
  -H "X-API-Key: your_app_key" \
  -H "Content-Type: application/json" \
  -d '{"slugs": ["abc123def456", "xyz789"]}'
{ "success": true, "deleted": ["abc123def456"], "failed": [{"slug":"xyz789","error":"not found"}], "deleted_count": 1, "failed_count": 1 }

Embed, iframe & image sizes

Every uploaded video, image, audio file, or PDF gets an embed_url that renders a clean, responsive player — drop it straight into any site with an iframe. No plan restriction beyond having API access at all (video, image, audio and PDF all just work).

GET/embed/:slugRenders an iframe-ready player for the file
<iframe
  src="https://cloud.alz.name.ng/embed/abc123def456"
  width="100%" height="360"
  frameborder="0"
  allow="autoplay; fullscreen; encrypted-media"
  allowfullscreen>
</iframe>
Query paramApplies toEffect
autoplay=0video, audioDisable autoplay (on by default)
muted=1videoStart muted — pair with autoplay for browsers that block unmuted autoplay
loop=1video, audioLoop playback

Video is streamed with full HTTP Range support, so seeking/scrubbing works properly and mobile browsers play it without buffering the whole file first — this is real progressive streaming, not a full-file download disguised as one.

Image size variants — append ?size= to any image's stream URL to get a smaller Telegram-generated variant instead of the original, useful for thumbnails/avatars without running your own resizing pipeline:

https://cloud.alz.name.ng/api/you/your-app/abc123/photo.jpg?size=small
https://cloud.alz.name.ng/api/you/your-app/abc123/photo.jpg?size=medium
https://cloud.alz.name.ng/api/you/your-app/abc123/photo.jpg?size=large
https://cloud.alz.name.ng/api/you/your-app/abc123/photo.jpg              (original, default)

The same file JSON also includes a sizes object with all four URLs pre-built, so you never have to construct these by hand:

"sizes": {
  "small": ".../photo.jpg?size=small",
  "medium": ".../photo.jpg?size=medium",
  "large": ".../photo.jpg?size=large",
  "original": ".../photo.jpg"
}

Forcing a download — add ?download=1 to any stream URL to send Content-Disposition: attachment instead of rendering inline. This is what download_url in every file response already points to, so a plain <a href="download_url">Download</a> just works, cross-site, without relying on the browser's download attribute.

Webhooks

Get notified the instant a file is uploaded or deleted instead of polling GET /files. Registered per app, authenticated with the same API key — no dashboard login needed.

POST/api/v1/webhooksBody: { url, events? }
curl -X POST https://cloud.alz.name.ng/api/v1/webhooks \
  -H "X-API-Key: your_app_key" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://yoursite.com/hooks/alzcloud", "events": ["file.uploaded","file.deleted"]}'
{
  "success": true, "id": 4, "url": "https://yoursite.com/hooks/alzcloud",
  "events": ["file.uploaded","file.deleted"], "active": true,
  "secret": "9f2c...  ← shown once, save it now"
}

Max 10 webhooks per app. The secret is only ever returned in this create response — it's used to verify deliveries below.

GET/api/v1/webhooksList your webhooks (no secrets returned)
DELETE/api/v1/webhooks/:id

Each delivery is a signed POST:

POST https://yoursite.com/hooks/alzcloud
X-AlzCloud-Event: file.uploaded
X-AlzCloud-Signature: hmac-sha256(secret, raw_body)

{ "event": "file.uploaded", "data": { ...file object... }, "sent_at": "..." }

Verify it came from AlzCloud by recomputing the HMAC-SHA256 of the raw request body with your webhook secret and comparing to the header. Delivery is fire-and-forget with a 5s timeout — a slow endpoint on your side never blocks or fails the upload/delete request that triggered it.

Managing apps (keys)

Creating/deleting apps and rotating or pausing keys are dashboard actions (session login), not part of the public API — a key can't be used to regenerate itself. Do these from My Apps, or the equivalent authenticated requests:

ActionRoute
Create appPOST /apps
Delete appDELETE /apps/:id
Rotate keyPOST /apps/:id/rotate
Pause / activatePATCH /apps/:id — { "revoked": true|false }

Pausing (revoke) keeps the app and its files intact and instantly blocks the key — use it the moment you suspect a leak, then rotate once you've updated wherever the key is used. Deleting an app removes it permanently and orphans its files.

CORS

The entire /api/v1/* surface, plus every file stream/embed URL, sends open CORS headers (Access-Control-Allow-Origin: *). You can call this API directly from client-side JavaScript on your own site — uploads, listing, deletes — without a server in between. Keep in mind that means anyone who can view your page's source can see whatever API key you embed in it; for public-facing upload widgets, consider a thin server-side proxy that injects the key instead of shipping it to the browser.