AlzCloud API
Programmatic file storage — upload, download, embed and stream, available on Starter and Pro. Manage keys under My Apps.
https://cloud.alz.name.ng/api/v1Authentication
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
| Code | Meaning |
|---|---|
| 401 | Missing, invalid, or revoked API key |
| 403 | API access not on your plan, or a quota reached |
| 404 | File / webhook / app not found |
| 400 | Bad request (missing fields, file too large) |
| 415 | File type can't be embedded |
| 429 | Rate limited — slow down (300 requests / 15 min per key) |
| 500 | Server error — try again later |
Status
{ "status": "ok", "version": "v1", "time": "2026-07-11T12:00:00.000Z" }
Account info
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.
{
"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.
{
"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.
| Param | Default |
|---|---|
| limit | 20 (max 100) |
| offset | 0 |
{
"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
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.
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
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.
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).
<iframe
src="https://cloud.alz.name.ng/embed/abc123def456"
width="100%" height="360"
frameborder="0"
allow="autoplay; fullscreen; encrypted-media"
allowfullscreen>
</iframe>
| Query param | Applies to | Effect |
|---|---|---|
| autoplay=0 | video, audio | Disable autoplay (on by default) |
| muted=1 | video | Start muted — pair with autoplay for browsers that block unmuted autoplay |
| loop=1 | video, audio | Loop 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.
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.
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:
| Action | Route |
|---|---|
| Create app | POST /apps |
| Delete app | DELETE /apps/:id |
| Rotate key | POST /apps/:id/rotate |
| Pause / activate | PATCH /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.