Hướng dẫn cho AI Agents (Claude Sessions, ChatGPT, Cursor, Replit Agents). Một endpoint POST /deploy/quick để deploy bất kỳ app nào lên production trong 60-90 giây.
POST https://zenicloud.io/api/v1/deploy/quick?ws=$WORKSPACEAuthorization: Bearer zeni_pat_xxx (PAT hoặc JWT)
Login dashboard zenicloud.io/app → Tab API Tokens → "+ New Token" → copy token bắt đầu bằng zeni_pat_
Đã có image trên Docker Hub / Artifact Registry / GCR samples? Deploy ngay:
curl -X POST "https://zenicloud.io/api/v1/deploy/quick?ws=$WORKSPACE" \
-H "Authorization: Bearer $ZENI_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"image": "docker.io/library/nginx:alpine",
"name": "my-static-site",
"port": 80
}'
Response (202):
{
"deploy_id": "...",
"method": "docker_image",
"status": "deploying",
"project_id": "uuid",
"poll_url": "https://zenicloud.io/api/v1/projects/{id}?ws=...",
"estimated_live_in_sec": 30
}
Poll poll_url sau 30s → status=running → có domain URL live.
Có code local? Zip + base64 + POST:
# Bash + Python (POSIX)
ZIP_B64=$(zip -qr - ./my-app/ | base64 -w0)
curl -X POST "https://zenicloud.io/api/v1/deploy/quick?ws=$WORKSPACE" \
-H "Authorization: Bearer $ZENI_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"zip_base64\":\"$ZIP_B64\",\"name\":\"my-app\",\"framework\":\"auto\"}"
Python (cross-platform):
import requests, zipfile, io, base64
buf = io.BytesIO()
with zipfile.ZipFile(buf, 'w', zipfile.ZIP_DEFLATED) as z:
z.writestr('index.html', '<h1>Hello World</h1>')
z.writestr('package.json', '{"name":"my-app"}')
r = requests.post(
'https://zenicloud.io/api/v1/deploy/quick',
params={'ws': 'your-workspace'},
headers={'Authorization': 'Bearer zeni_pat_xxx'},
json={
'zip_base64': base64.b64encode(buf.getvalue()).decode(),
'name': 'my-app',
'framework': 'auto', # auto-detect from package.json/requirements.txt
'port': 8080
}
)
print(r.json())
# → {"deploy_id":"...", "poll_url":"...", "status":"queued"}
Poll poll_url mỗi 10s. Status: queued → extracting → building → deploying → success
Repo public trên GitHub? Paste URL → Zeni clone + build + deploy:
curl -X POST "https://zenicloud.io/api/v1/deploy/quick?ws=$WORKSPACE" \
-H "Authorization: Bearer $ZENI_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"repo_url": "https://github.com/owner/repo",
"branch": "main",
"name": "my-app",
"framework": "auto"
}'
Zeni Cloud tự nhận diện framework từ files trong ZIP/repo:
| Detect file | Framework | Auto-Dockerfile | Default port |
|---|---|---|---|
next.config.js | Next.js | node:20-alpine + standalone build | 3000 |
vite.config.js | React/Vite | node:20 build → nginx serve | 80 |
vue.config.js | Vue.js | node:20 build → nginx serve | 80 |
requirements.txt | FastAPI (default Python) | python:3.12-slim + uvicorn | 8080 |
package.json (no Next/Vite) | Express.js | node:20-alpine + npm start | 3000 |
index.html only | Static HTML | nginx:alpine + serve | 80 |
Dockerfile exists | Custom | Use repo's Dockerfile as-is | (detected) |
Override bằng "framework": "nextjs|react|vue|fastapi|express|static"
curl "$POLL_URL" -H "Authorization: Bearer $ZENI_TOKEN"
# Response:
{
"deploy_id": "...",
"status": "building", # queued|extracting|building|deploying|success|failed
"name": "my-app",
"framework": "express",
"image_url": null, # populated khi build SUCCESS
"deploy_url": null, # populated khi deploy SUCCESS
"error": null,
"completed_at": null
}
# Khi success:
{
"deploy_id": "...",
"status": "success",
"image_url": "us-central1-docker.pkg.dev/zeni-cloud-core/zeni-images/zeni-myws-myapp:abc123",
"deploy_url": "https://my-app-xxx-uc.a.run.app",
"completed_at": "2026-05-03T..."
}
// Pseudocode for Claude Code:
1. User: "Deploy my Next.js app at /home/user/my-app to Zeni Cloud"
2. Bash: cd /home/user/my-app && zip -qr /tmp/app.zip ./
3. Python: read /tmp/app.zip, base64 encode
4. curl POST /deploy/quick with zip_base64
5. Loop: poll /deploy/quick/{id} every 10s until status='success'
6. Return deploy_url to user
import requests, zipfile, base64
from pathlib import Path
# Upload + deploy in one cell
def deploy_to_zeni(folder_path, ws, token, name=None, framework='auto'):
buf = io.BytesIO()
with zipfile.ZipFile(buf, 'w', zipfile.ZIP_DEFLATED) as z:
for f in Path(folder_path).rglob('*'):
if f.is_file() and 'node_modules' not in str(f) and '.git' not in str(f):
z.write(f, f.relative_to(folder_path))
r = requests.post(f'https://zenicloud.io/api/v1/deploy/quick',
params={'ws': ws},
headers={'Authorization': f'Bearer {token}'},
json={'zip_base64': base64.b64encode(buf.getvalue()).decode(),
'name': name or folder_path.split('/')[-1], 'framework': framework})
return r.json()
Same pattern: zip current workspace → POST /deploy/quick → poll → return URL.
framework: "auto" trừ khi user explicit overrideregion: asia-southeast1 (Singapore — gần VN nhất)node_modules/, .git/, __pycache__/ khi zip — giảm size| Endpoint | Purpose |
|---|---|
POST /api/v1/deploy/quick?ws=X | One-call deploy (3 input methods) |
GET /api/v1/deploy/quick/{id}?ws=X | Poll status |
POST /api/v1/upload/source?ws=X | Multipart ZIP upload (alternative to base64) |
GET /api/v1/projects?ws=X | List all deployed projects |
POST /api/v1/projects?ws=X | Full custom deploy (more options) |
🤖 Designed for AI agents. Tối giản, idempotent, single-call. Built by Zeni Cloud.