HelipodDocs

Templates and stacks

Create several connected services in one request, from the template gallery or your own spec.

GET/containers/templates
Published templates. ?search= and ?category= filter the list.
{
  "success": true,
  "data": [
    { "slug": "wordpress", "name": "WordPress", "description": "…", "category": "CMS", "verified": true, "services": ["WordPress", "MySQL"], "deployCount": 128 }
  ]
}

Browse them with screenshots and descriptions at helipod.io/templates.

POST/containers/environments/{environmentId}/templates/{slug}charges your walletIdempotency-Key

Creates every service of the template in the environment and deploys them, dependencies first.

curl -X POST https://api.helipod.io/api/containers/environments/$ENV/templates/wordpress \
  -H "Authorization: Bearer hel_your_key" -H "Content-Type: application/json" \
  -d '{ "inputs": {} }'

inputs fills the questions a template asks (an admin email, a registry token, ...). Required inputs that are missing are refused with the list of what to fill in. The response (201) is { "services": [ { "service": { ... }, "deploymentId": "..." } ] }.

Stacks: your own spec

POST/containers/environments/{environmentId}/stackscharges your walletdryRunIdempotency-Key

Creates the services of a template spec, wired together, and deploys them.

A stack uses the same format as Helipod templates. Services reference each other's variables, and get deployed in dependency order.

Request body
{
  "spec": {
    "version": 1,
    "inputs": [{ "key": "ADMIN_EMAIL", "label": "Admin email", "required": true }],
    "services": [
      {
        "key": "db",
        "name": "Postgres",
        "source": { "image": "postgres:16-alpine" },
        "variables": {
          "POSTGRES_USER": "app",
          "POSTGRES_PASSWORD": "${{secret(32)}}",
          "POSTGRES_DB": "app",
          "DATABASE_URL": "postgres://app:${{POSTGRES_PASSWORD}}@${{HELIPOD_PRIVATE_DOMAIN}}:5432/app"
        },
        "networking": { "tcp": [{ "port": 5432 }] },
        "volumes": [{ "mountPath": "/var/lib/postgresql/data", "sizeGb": 5 }]
      },
      {
        "key": "app",
        "name": "App",
        "source": { "repo": "https://github.com/acme/app", "branch": "main" },
        "variables": { "DATABASE_URL": "${{Postgres.DATABASE_URL}}", "ADMIN_EMAIL": "${{input.ADMIN_EMAIL}}" },
        "networking": { "http": [{ "port": 3000, "public": true }] },
        "healthcheck": { "path": "/health" },
        "dependsOn": ["db"]
      }
    ]
  },
  "inputs": { "ADMIN_EMAIL": "[email protected]" }
}

Prop

Type

Variable values can use:

  • ${{input.KEY}} for an input,
  • ${{secret(32)}} and ${{uuid}} for a random value generated once,
  • ${{Service.KEY}} for a variable of another service in the stack (or already in the environment),
  • ${{KEY}} for another variable of the same service,
  • values Helipod provides: ${{PORT}}, ${{HELIPOD_PRIVATE_DOMAIN}} (host name inside the environment), ${{HELIPOD_PUBLIC_DOMAIN}}, ${{HELIPOD_TCP_PROXY_DOMAIN}} and ${{HELIPOD_TCP_PROXY_PORT}} (public TCP address), ${{HELIPOD_SERVICE_NAME}} and ${{HELIPOD_ENVIRONMENT_NAME}}. Each also works on another service: ${{Postgres.HELIPOD_PRIVATE_DOMAIN}}.

For a private image, source.auth must reference inputs ({ "username": "${{input.REGISTRY_USER}}", "password": "${{input.REGISTRY_TOKEN}}" }) so credentials are never part of the spec itself.

Add ?dryRun=true to get the daily cost of every service without creating anything. Invalid specs are refused with 400 INVALID_SPEC and the first problem found.

On this page