Skip to main content
A template is a configuration bundle that stores default settings for instance creation. Instead of passing every parameter each time you create an instance, you define a template once and reference it by its hash_id. You can optionally override specific values at creation time. Templates are useful for:
  • Standardization — ensure all team members launch instances with consistent configurations
  • Convenience — avoid repeating the same image, env, and onstart parameters across calls
  • Sharing — distribute configurations via template hash ID
For information about managing templates in the web interface, see Templates Introduction.

Setup

from vastai_sdk import VastAI

vast_sdk = VastAI(api_key="YOUR_API_KEY")

Template Fields Reference

When creating or editing a template, the following fields can be configured:
FieldTypeSDK ParameterDescription
namestringnameHuman-readable name for the template
imagestringimageDocker image path (e.g., vllm/vllm-openai)
tagstringimage_tagDocker image tag. Defaults to latest
descstringdescShort description of the template
readmestringreadmeLonger documentation/readme content
envstringenvEnvironment variables and port mappings in Docker flag format (e.g., "-e VAR=val -p 8000:8000")
onstartstringonstart_cmdShell commands to run when the instance starts
runtypestringssh / jupyterLaunch mode: ssh, jupyter, or args (default). Set via boolean flags
ssh_directbooleanssh=True, direct=TrueEnable direct SSH (set by combining ssh and direct)
use_sshbooleansshEnable SSH access
jup_directbooleanjupyter=True, direct=TrueEnable direct Jupyter (set by combining jupyter and direct)
jupyter_dirstringjupyter_dirDirectory to launch Jupyter from
use_jupyter_labbooleanjupyter_labUse JupyterLab instead of Jupyter Notebook
docker_login_repostringloginPrivate Docker registry URL (first token of the login string)
extra_filtersobjectsearch_paramsDefault machine search filters (parsed from query string)
recommended_disk_spacenumberdisk_spaceRecommended disk space in GB
privateboolean(private by default)Templates are private by default
hrefstringhrefLink to Docker Hub or image documentation
repostringrepoRepository identifier

Template Identifiers

Templates have two identifiers. Which one you use depends on the operation:
IdentifierTypeUsed For
idintegerDeleting templates (template_id parameter)
hash_idstringCreating instances (template_hash parameter), editing templates (HASH_ID parameter)
The hash_id is derived from the template’s content. After editing a template, the hash_id changes. Always retrieve the latest hash_id from the method return value or by searching for the template.

Create a Template

Use create_template() to define a reusable configuration:
result = vast_sdk.create_template(
    name="vLLM Inference Server",
    image="vllm/vllm-openai",
    image_tag="latest",
    env="-e MODEL_ID=deepseek-ai/DeepSeek-R1-Distill-Llama-8B -p 8000:8000",
    onstart_cmd='echo "Starting vLLM server"; vllm serve $MODEL_ID',
    disk_space="50",
    ssh=True,
    direct=True
)
print(result)
The result includes both identifiers:
New Template: {'id': 334548, 'hash_id': '4e17788f74f075dd9aab7d0d4427968f', ...}
Save both the id and hash_id — you’ll need them for different operations. You can also attach default machine search filters using search_params:
result = vast_sdk.create_template(
    name="tgi-llama2-7B-quantized",
    image="ghcr.io/huggingface/text-generation-inference:1.0.3",
    env="-p 3000:3000 -e MODEL_ARGS='--model-id TheBloke/Llama-2-7B-chat-GPTQ --quantize gptq'",
    onstart_cmd="wget -O - https://raw.githubusercontent.com/vast-ai/vast-pyworker/main/scripts/launch_tgi.sh | bash",
    search_params="gpu_ram>=23 num_gpus=1 gpu_name=RTX_3090 inet_down>128 direct_port_count>3 disk_space>=192",
    disk_space="8.0",
    ssh=True,
    direct=True
)

Method Signature

VastAI.create_template(
    name: Optional[str] = None,
    image: Optional[str] = None,
    image_tag: Optional[str] = None,
    login: Optional[str] = None,
    env: Optional[str] = None,
    ssh: bool = False,
    jupyter: bool = False,
    direct: bool = False,
    jupyter_dir: Optional[str] = None,
    jupyter_lab: bool = False,
    onstart_cmd: Optional[str] = None,
    search_params: Optional[str] = None,
    disk_space: Optional[str] = None
) -> str

Search for Templates

Use search_templates() with the same query syntax used by search_offers():
# Search for popular templates (more than 100 instances created)
result = vast_sdk.search_templates(query="count_created > 100")
print(result)

# Search for templates by specific creators
result = vast_sdk.search_templates(
    query="count_created > 100 creator_id in [38382,48982]"
)

# Search for recommended templates with SSH support
result = vast_sdk.search_templates(
    query="recommended == True use_ssh == True"
)

Query Syntax

query = comparison comparison ...
comparison = field op value
op = one of: <, <=, ==, !=, >=, >, in, notin

Searchable Fields

FieldTypeDescription
creator_idintID of the creator
created_atfloatTime of initial creation (UTC epoch)
count_createdintNumber of instances created (popularity)
default_tagstringImage default tag
docker_login_repostringImage docker repository
idintTemplate unique ID
imagestringImage used for the template
jup_directboolSupports Jupyter direct
hash_idstringUnique hash ID
namestringDisplayable name
recent_create_datefloatLast time of instance creation (UTC epoch)
recommended_disk_spacefloatMinimum disk space required
recommendedboolOn the recommended list
ssh_directboolSupports SSH direct
tagstringImage tag
use_sshboolSupports SSH (direct or proxy)

Method Signature

VastAI.search_templates(query: Optional[str] = None) -> str

Create an Instance from a Template

Pass template_hash to create_instance() to use a template as the base configuration. You don’t need to specify image or other fields already defined in the template:
result = vast_sdk.create_instance(
    id=12345678,
    template_hash="4e17788f74f075dd9aab7d0d4427968f",
    disk=20
)
print(result)
Output:
{"success": true, "new_contract": 7835610}
You can combine a template with an interruptible (spot) bid:
result = vast_sdk.create_instance(
    id=12345678,
    template_hash="4e17788f74f075dd9aab7d0d4427968f",
    disk=64,
    price=0.10
)

Override Template Values

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 (string)Merged. Template values retained, request values appended. Conflicting keys use the request value
extra_filters (dict)Merged by key. Request values win on conflicts

Example: Overriding the Image

# Use template config but swap the Docker image
result = vast_sdk.create_instance(
    id=12345678,
    template_hash="4e17788f74f075dd9aab7d0d4427968f",
    image="nvidia/cuda:12.1-devel-ubuntu22.04",
    disk=20
)

Example: Merging Environment Variables

If your template defines:
env: "-e MODEL_ID=deepseek-ai/DeepSeek-R1-Distill-Llama-8B -e MAX_TOKENS=4096"
And you create an instance with:
result = vast_sdk.create_instance(
    id=12345678,
    template_hash="4e17788f74f075dd9aab7d0d4427968f",
    env="-e MODEL_ID=mistralai/Mistral-7B-v0.1 -e HF_TOKEN=hf_xxx",
    disk=20
)
The resulting environment will be:
  • MODEL_ID=mistralai/Mistral-7B-v0.1 — request overrides template
  • MAX_TOKENS=4096 — retained from template
  • HF_TOKEN=hf_xxx — added from request

Edit a Template

Update an existing template using update_template() with the template’s hash_id as the HASH_ID parameter. Include only the parameters you want to change:
result = vast_sdk.update_template(
    HASH_ID="5915f1dc1ce881defb572015eb9d8178",
    name="Updated Template Name",
    onstart_cmd="echo 'new startup script'"
)
print(result)
You can change any of the same parameters available in create_template():
result = vast_sdk.update_template(
    HASH_ID="c81e7ab0e928a508510d1979346de10d",
    name="tgi-llama2-7B-quantized",
    image="ghcr.io/huggingface/text-generation-inference:1.0.3",
    env="-p 3000:3000 -e MODEL_ARGS='--model-id TheBloke/Llama-2-7B-chat-GPTQ --quantize gptq'",
    onstart_cmd="wget -O - https://raw.githubusercontent.com/vast-ai/vast-pyworker/main/scripts/launch_tgi.sh | bash",
    ssh=True,
    direct=True
)
The hash_id changes after editing because it is derived from the template’s content. Use the new hash_id returned in the result for subsequent operations.

Method Signature

VastAI.update_template(
    HASH_ID: str,
    name: Optional[str] = None,
    image: Optional[str] = None,
    env: Optional[str] = None,
    onstart_cmd: Optional[str] = None,
    search_params: Optional[str] = None,
    disk: Optional[float] = None,
    ssh: bool = False,
    direct: bool = False,
    jupyter: bool = False
) -> str

Delete a Template

Delete a template using either its numeric id or its hash_id:
# Delete by numeric ID
result = vast_sdk.delete_template(template_id=334548)
print(result)

# Delete by hash ID
result = vast_sdk.delete_template(hash_id="49c538d097ad6437413b83711c9f61e8")
print(result)
Deleting a template removes your relationship to it. It does not destroy the underlying template record.

Method Signature

VastAI.delete_template(
    template_id: Optional[int] = None,
    hash_id: Optional[str] = None
) -> str

Common Pitfalls

Templates have two identifiers and each is used in different contexts:
  • create_instance(template_hash=...) takes the hash_id (string)
  • update_template(HASH_ID=...) takes the hash_id (string)
  • delete_template(template_id=...) takes the numeric id (integer)
If you pass the numeric id where a hash_id is expected (or vice versa), the operation will fail. You can also call delete_template(hash_id=...) with the hash if you don’t have the numeric ID.
The env parameter expects Docker flag format as a single string, not key=value pairs or a dictionary:
# Correct
env="-e VAR1=value1 -e VAR2=value2 -p 8000:8000"

# Wrong -- missing -e prefix
env="VAR1=value1 VAR2=value2"

# Wrong -- not a dict
env={"VAR1": "value1"}
Port mappings are also specified in this string using -p:
env="-e MY_VAR=hello -p 8080:8080 -p 8081:8081/udp"
When you specify both template_hash and image in create_instance(), the image parameter overrides the template’s image. If you want to use the template’s image, omit the image parameter entirely.
The volume_info field stored in templates is a UI hint only. To actually mount a volume, you must pass volume information in the instance creation request. Use the API directly or the CLI volume flags for this:
# Link an existing volume (CLI)
vastai create instance 12345678 --template_hash abc123 \
  --link-volume 12345 --mount-path /workspace

# Create a new volume (CLI)
vastai create instance 12345678 --template_hash abc123 \
  --create-volume 28908979 --volume-size 10 --mount-path /workspace
See the API templates page for the JSON volume_info structure.
This is expected behavior. The hash_id is content-based, so any edit produces a new hash. Always capture the new hash_id from the update_template() return value or search for your template again before referencing it.