Skip to main content

Introduction

A template in the Vast.ai API is a configuration bundle that stores default settings for instance creation. Instead of specifying every parameter each time you create an instance, you can reference a template by its hash_id and optionally override specific values. Templates are useful for:
  • Standardization: Ensure all team members launch instances with consistent configurations
  • Convenience: Avoid repeating the same parameters across multiple API calls
  • Sharing: Share configurations via template hash ID
For information about managing templates in the web interface, see Templates Introduction.

Template Fields Reference

When creating a template, the following fields can be configured:
FieldTypeDescription
namestringRequired. Human-readable name for the template
imagestringRequired. Docker image path (e.g., vastai/pytorch)
tagstringDocker image tag. Defaults to latest
descstringDescription of the template
readmestringLonger documentation/readme content
envstringEnvironment variables and port mappings in Docker flag format (e.g., "-e VAR=val -p 8000:8000")
onstartstringShell commands to run when instance starts
runtypestringLaunch mode: ssh, jupyter, or args. Defaults to args
args_strstringReplaces the image’s Docker CMD. If the image defines an ENTRYPOINT, this is passed as arguments to it
ssh_directbooleanEnable direct SSH connection (recommended with runtype: "ssh")
use_sshbooleanEnable SSH access
jup_directbooleanEnable direct Jupyter connection
jupyter_dirstringDirectory to launch Jupyter from
use_jupyter_labbooleanUse JupyterLab instead of Jupyter Notebook
docker_login_repostringRequired (use "" if not needed). Private Docker registry URL
docker_login_userstringRequired (use "" if not needed). Username for private registry
docker_login_passstringRequired (use "" if not needed). Access token for private registry
hrefstringLink to Docker Hub or image documentation
repostringRepository identifier (e.g., library/ubuntu)
extra_filtersobjectDefault machine search filters (e.g., {"cuda_max_good": {"gte": 12.6}})
recommended_disk_spacenumberRecommended disk space in GB (default: 8)
privatebooleanWhether the template is private
volume_infoobjectUI hint for volume configuration (not used for actual instance creation)

Template Identifiers

Templates have two primary identifiers:
IdentifierTypeDescription
idintegerNumeric identifier. Used for deleting templates
hash_idstringContent-based hash. Used for creating instances and editing templates
Usage by operation:
  • Create instance: Use template_hash_id
  • Edit template: Use hash_id (via PUT)
  • Delete template: Use numeric id

Precedence Rules

When you create an instance with both a template and additional parameters, the following precedence rules apply:
Field TypeBehavior
Scalar fields (image, disk, runtype, etc.)Request value overrides template value
env (dict)Merged. Template values retained, request values added. Conflicting keys use request value
extra_filters (dict)Merged by key. Request values win on conflicts

Example: Environment Variables

When creating an instance, the env field is passed as a JSON object (dict). When you provide env in your request, it is merged with the template’s env — existing values are retained and new values are added.
Templates store env as a Docker flag string (e.g., "-e VAR=val -p 8000:8000"), but instance creation uses a dict format. The API handles the conversion automatically when merging.
Template configuration (string format):
{
  "env": "-e MODEL_ID=deepseek-ai/DeepSeek-R1-Distill-Llama-8B -e MAX_TOKENS=4096"
}
Instance creation request (dict format):
{
  "template_hash_id": "4e17788f74f075dd9aab7d0d4427968f",
  "env": {
    "MODEL_ID": "mistralai/Mistral-7B-v0.1",
    "HF_TOKEN": "hf_xxx"
  }
}
Resulting instance environment:
  • MODEL_ID=mistralai/Mistral-7B-v0.1 (request overrides template)
  • MAX_TOKENS=4096 (retained from template)
  • HF_TOKEN=hf_xxx (added from request)

Cookbook Examples

Search for Templates

Search for templates using select_filters with comparison operators. Query Syntax:
select_filters = { "field": { "op": value } }
Operators: eq, neq, lt, lte, gt, gte, in, notin Available Fields:
FieldTypeDescription
creator_idintID of creator
created_atfloatTime of initial template creation (UTC epoch)
count_createdintNumber of instances created (popularity)
default_tagstringImage default tag
docker_login_repostringImage docker repository
idintTemplate unique ID
imagestringImage used for template
jup_directboolSupports jupyter direct
hash_idstringUnique hash ID of template
namestringDisplayable name
recent_create_datefloatLast time of instance creation (UTC epoch)
recommended_disk_spacefloatMin disk space required
recommendedboolIs template on recommended list
ssh_directboolSupports SSH direct
tagstringImage tag
use_sshboolSupports SSH (direct or proxy)
# Search for recommended templates with SSH support
curl -G "https://console.vast.ai/api/v0/template/" \
  -H "Authorization: Bearer $VAST_API_KEY" \
  --data-urlencode 'select_filters={"use_ssh":{"eq":true},"recommended":{"eq":true}}'

# Search for popular templates (more than 100 instances created)
curl -G "https://console.vast.ai/api/v0/template/" \
  -H "Authorization: Bearer $VAST_API_KEY" \
  --data-urlencode 'select_filters={"count_created":{"gt":100}}'

Create a New Template

Create a reusable template. This example shows a recommended configuration with SSH direct access.
curl -X POST "https://console.vast.ai/api/v0/template/" \
  -H "Authorization: Bearer $VAST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Example Template",
    "desc": "Template for running vLLM inference server",
    "image": "vllm/vllm-openai",
    "tag": "latest",
    "env": "-e MODEL_ID=deepseek-ai/DeepSeek-R1-Distill-Llama-8B -p 8000:8000",
    "onstart": "echo \"Starting vLLM server\"; vllm serve $MODEL_ID",
    "runtype": "ssh",
    "ssh_direct": true,
    "use_ssh": true,
    "docker_login_repo": "",
    "docker_login_user": "",
    "docker_login_pass": "",
    "recommended_disk_space": 50,
    "private": true
  }'

Full Template Example

Here’s a complete template creation request with all common fields:
{
  "name": "Example Template",
  "desc": "Description of what this template does",
  "readme": "Longer documentation\nwith multiple lines",
  "image": "library/ubuntu",
  "tag": "22.04",
  "repo": "library/ubuntu",
  "href": "https://hub.docker.com/r/library/ubuntu/",
  "env": "-e ENV1=val1 -p 8000:8000",
  "onstart": "echo \"hello\"",
  "args_str": "",
  "runtype": "ssh",
  "ssh_direct": true,
  "use_ssh": true,
  "jup_direct": true,
  "jupyter_dir": null,
  "use_jupyter_lab": false,
  "docker_login_repo": "",
  "docker_login_user": "",
  "docker_login_pass": "",
  "extra_filters": {"cuda_max_good": {"gte": 12.6}},
  "recommended_disk_space": 8,
  "private": true,
  "volume_info": null
}

Edit a Template

Edit an existing template using its hash_id. You only need to include the fields you want to change - unchanged fields retain their existing values.
curl -X PUT "https://console.vast.ai/api/v0/template/" \
  -H "Authorization: Bearer $VAST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "hash_id": "5915f1dc1ce881defb572015eb9d8178",
    "desc": "Updated description",
    "recommended_disk_space": 16
  }'
The hash_id will change after editing since it is derived from the template content.

Delete a Template

Delete a template by passing its numeric id (not hash_id) in the request body.
curl -X DELETE "https://console.vast.ai/api/v0/template/" \
  -H "Authorization: Bearer $VAST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"template_id": 334548}'

Create Instance from Template

Launch an instance using a template. No need to specify image as the template provides it.
curl -X PUT "https://console.vast.ai/api/v0/asks/12345678/" \
  -H "Authorization: Bearer $VAST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template_hash_id": "4e17788f74f075dd9aab7d0d4427968f"
  }'

Create Instance with Image Override

Use a template but specify a different Docker image.
curl -X PUT "https://console.vast.ai/api/v0/asks/12345678/" \
  -H "Authorization: Bearer $VAST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template_hash_id": "4e17788f74f075dd9aab7d0d4427968f",
    "image": "library/ubuntu:22.04"
  }'

Override Environment Variables

Override template environment variables with new values. Instance creation uses the dict format for env.
curl -X PUT "https://console.vast.ai/api/v0/asks/12345678/" \
  -H "Authorization: Bearer $VAST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template_hash_id": "4e17788f74f075dd9aab7d0d4427968f",
    "env": {"MODEL_ID": "mistralai/Mistral-7B-Instruct-v0.2", "HF_TOKEN": "hf_xxxYourTokenHere", "-p 8000:8000": "1"}
  }'

Create Instance with Volume

Attach a volume when creating an instance. You can either link an existing volume or create a new one.
The volume_info field stored in templates is a UI hint only. To actually attach a volume, you must include volume_info in the instance creation request.
Link an existing volume:
curl -X PUT "https://console.vast.ai/api/v0/asks/12345678/" \
  -H "Authorization: Bearer $VAST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template_hash_id": "4e17788f74f075dd9aab7d0d4427968f",
    "volume_info": {
      "create_new": false,
      "volume_id": 12345,
      "mount_path": "/workspace"
    }
  }'
Create a new volume:
curl -X PUT "https://console.vast.ai/api/v0/asks/12345678/" \
  -H "Authorization: Bearer $VAST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template_hash_id": "4e17788f74f075dd9aab7d0d4427968f",
    "volume_info": {
      "create_new": true,
      "volume_id": 28908979,
      "size": 10,
      "mount_path": "/workspace"
    }
  }'
CLI equivalent:
# Link existing volume
vastai create instance 12345678 --template_hash abc123 --link-volume 12345 --mount-path /workspace

# Create new volume
vastai create instance 12345678 --template_hash abc123 --create-volume 28908979 --volume-size 10 --mount-path /workspace

CLI Reference

The Vast.ai CLI provides commands for template management:
CommandDescription
vastai create template --name <name> --image <image> [options]Create a new template
vastai search templates [filters]Search for templates
vastai update template <hash_id> [options]Update a template (uses hash_id)
vastai delete template --template-id <id>Delete a template (uses numeric id)
Create template options:
  • --name NAME - Template name
  • --image IMAGE - Docker image
  • --image_tag TAG - Image tag
  • --env ENV - Docker options (env vars and ports)
  • --ssh - Launch as SSH instance
  • --jupyter - Launch as Jupyter instance
  • --direct - Use direct connections
  • --onstart-cmd CMD - Onstart script
  • --disk_space GB - Disk space in GB
  • --desc DESC - Description
  • --readme README - Readme content
  • --public - Make template public
The CLI update template command takes hash_id as its argument, while delete template uses the numeric id.

Runtype and Connection Options

The runtype field controls the launch mode of your instance:
RuntypeDescription
argsDefault. args_str replaces the image’s CMD and is passed to its ENTRYPOINT if one is defined
sshSSH access enabled. Recommended with ssh_direct: true
jupyterJupyter notebook/lab access
Recommendation: Use runtype: "ssh" with ssh_direct: true and use_ssh: true for reliable SSH access to your instances. The args_str field is used when runtype is args. It replaces the image’s Docker CMD — if the image defines an ENTRYPOINT, args_str is passed as arguments to it. If the image has no ENTRYPOINT (only CMD), args_str replaces the command entirely.
{
  "runtype": "args",
  "args_str": "--model deepseek-ai/DeepSeek-R1-Distill-Llama-8B --port 8000"
}

Common Pitfalls

Instance creation requires template_hash_id, not template_id. The numeric id is only used for deleting templates. Use the hash_id returned when you create or search for templates:
{
  "template_hash_id": "4e17788f74f075dd9aab7d0d4427968f"
}
When you specify both template_hash_id and image, the request’s image overrides the template’s image. If you want to use the template’s image, omit the image field from your request.
Template creation and instance creation use different formats for the env field:
  • Templates: Docker flag string format — "-e VAR1=value1 -e VAR2=value2 -p 8000:8000"
  • Instance creation: Dict format — {"VAR1": "value1", "VAR2": "value2", "-p 8000:8000": "1"}
When creating an instance with a template, the request env (dict) is merged with the template env — existing keys are overwritten, new keys are added.
When creating instances, port mappings are specified in the env dict using the -p syntax as keys:
{
  "env": {
    "-p 8000:8000": "1",
    "-p 8080:8080": "1"
  }
}
For SSH access, use runtype: "ssh" with ssh_direct: true.
Volume mounting uses the volume_info structure in the instance creation request. Note that volume_info in templates is just a UI hint and doesn’t affect instance creation.To link an existing volume:
{
  "volume_info": {
    "create_new": false,
    "volume_id": 12345,
    "mount_path": "/workspace"
  }
}
To create a new volume:
{
  "volume_info": {
    "create_new": true,
    "volume_id": 28908979,
    "size": 10,
    "mount_path": "/workspace"
  }
}
Where:
  • volume_id is either an existing volume ID (from show volumes) or a volume offer ID (from search volumes)
  • size is only used when create_new is true
  • mount_path is where the volume mounts inside the container
Template search uses select_filters with comparison operators, not free-text search:
  • Use the correct filter syntax: {"field": {"op": value}}
  • Valid operators: eq, neq, lt, lte, gt, gte, in, notin
  • Verify your API key has user_read permissions
  • Check available fields in the search documentation above