Quickstart
Deploy a container, give it a domain and watch it go live, in five requests.
This guide deploys nginx:alpine as a public website. You need a Helipod API key with Container API enabled.
export HELIPOD_KEY=hel_your_key
export API=https://api.helipod.io/api/containersFind your environment
curl $API/projects -H "Authorization: Bearer $HELIPOD_KEY"{
"success": true,
"data": [
{
"id": "3b0cd5ac-ac26-4012-9b28-17466f73788c",
"name": "My Shop",
"description": null,
"createdAt": "2026-09-01T08:00:00.000Z",
"environments": [
{ "id": "e1d4a0f2-6c11-4a9e-8a0e-5f2b7d1c9a33", "name": "production" }
]
}
]
}export ENV=e1d4a0f2-6c11-4a9e-8a0e-5f2b7d1c9a33Check the price
curl -X POST "$API/environments/$ENV/services?dryRun=true" \
-H "Authorization: Bearer $HELIPOD_KEY" -H "Content-Type: application/json" \
-d '{ "name": "web", "source": { "image": "nginx:alpine" }, "ports": [{ "port": 80 }] }'{ "success": true, "data": { "dryRun": true, "currency": "IDR", "dailyCost": 350, "services": [ { "name": "web", "cpu": 125, "ram": 128, "storageMb": 0, "dailyCost": 350 } ] } }Create and deploy the service
The same request without dryRun. It creates the service, gives port 80 a *.helipod.app domain and starts the first deploy.
curl -X POST "$API/environments/$ENV/services" \
-H "Authorization: Bearer $HELIPOD_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: quickstart-web-1" \
-d '{ "name": "web", "source": { "image": "nginx:alpine" }, "ports": [{ "port": 80 }] }'{
"success": true,
"data": {
"service": {
"id": "9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d",
"name": "web",
"status": "pending",
"domains": [ { "id": "…", "kind": "helipod", "domain": "web.helipod.app", "port": 80, "protocol": "http", "status": "active", "url": "https://web.helipod.app" } ],
"dailyCost": 350
},
"deploymentId": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f"
}
}Wait for the deploy
Poll the deployment until it is success or failed:
curl $API/services/$SERVICE/deployments/$DEPLOYMENT -H "Authorization: Bearer $HELIPOD_KEY"{ "success": true, "data": { "id": "0c1d…", "serviceId": "9a8b…", "status": "success", "createdAt": "2026-10-16T09:12:03.000Z" } }If it failed, read the build and deploy log: GET $API/services/$SERVICE/deployments/$DEPLOYMENT/logs.
Open it
The service is live at the url of its domain. From here you can set variables, add your own domain or scale it.
const API = "https://api.helipod.io/api/containers";
const headers = { Authorization: `Bearer ${process.env.HELIPOD_KEY}`, "Content-Type": "application/json" };
const call = async (method, path, body, extra = {}) => {
const res = await fetch(API + path, { method, headers: { ...headers, ...extra }, body: body && JSON.stringify(body) });
const json = await res.json();
if (!json.success) throw new Error(`${res.status} ${json.code}: ${json.error}`);
return json.data;
};
const [project] = await call("GET", "/projects");
const env = project.environments.find((e) => e.name === "production");
const { service, deploymentId } = await call("POST", `/environments/${env.id}/services`, {
name: "web",
source: { image: "nginx:alpine" },
ports: [{ port: 80 }],
}, { "Idempotency-Key": `web-${env.id}` });
let status = "pending";
while (!["success", "failed", "cancelled"].includes(status)) {
await new Promise((r) => setTimeout(r, 5000));
({ status } = await call("GET", `/services/${service.id}/deployments/${deploymentId}`));
}
console.log(status, service.domains[0]?.url);