HelipodDocs

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/containers

Find 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-5f2b7d1c9a33

Check 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.

deploy.mjs
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);

On this page