Create Application
curl --request POST \
--url https://api.vertracloud.app/v1/apps \
--header 'Content-Type: application/json' \
--data '
{
"snapshot_id": "<string>",
"memory": "<string>",
"start": "<string>",
"build": "<string>",
"main": "<string>",
"version": "<string>",
"name": "<string>",
"description": "<string>",
"workspace_id": "<string>",
"subdomain": "<string>",
"envs": "<string>"
}
'import requests
url = "https://api.vertracloud.app/v1/apps"
payload = {
"snapshot_id": "<string>",
"memory": "<string>",
"start": "<string>",
"build": "<string>",
"main": "<string>",
"version": "<string>",
"name": "<string>",
"description": "<string>",
"workspace_id": "<string>",
"subdomain": "<string>",
"envs": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
snapshot_id: '<string>',
memory: '<string>',
start: '<string>',
build: '<string>',
main: '<string>',
version: '<string>',
name: '<string>',
description: '<string>',
workspace_id: '<string>',
subdomain: '<string>',
envs: '<string>'
})
};
fetch('https://api.vertracloud.app/v1/apps', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.vertracloud.app/v1/apps",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'snapshot_id' => '<string>',
'memory' => '<string>',
'start' => '<string>',
'build' => '<string>',
'main' => '<string>',
'version' => '<string>',
'name' => '<string>',
'description' => '<string>',
'workspace_id' => '<string>',
'subdomain' => '<string>',
'envs' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.vertracloud.app/v1/apps"
payload := strings.NewReader("{\n \"snapshot_id\": \"<string>\",\n \"memory\": \"<string>\",\n \"start\": \"<string>\",\n \"build\": \"<string>\",\n \"main\": \"<string>\",\n \"version\": \"<string>\",\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"workspace_id\": \"<string>\",\n \"subdomain\": \"<string>\",\n \"envs\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.vertracloud.app/v1/apps")
.header("Content-Type", "application/json")
.body("{\n \"snapshot_id\": \"<string>\",\n \"memory\": \"<string>\",\n \"start\": \"<string>\",\n \"build\": \"<string>\",\n \"main\": \"<string>\",\n \"version\": \"<string>\",\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"workspace_id\": \"<string>\",\n \"subdomain\": \"<string>\",\n \"envs\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vertracloud.app/v1/apps")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"snapshot_id\": \"<string>\",\n \"memory\": \"<string>\",\n \"start\": \"<string>\",\n \"build\": \"<string>\",\n \"main\": \"<string>\",\n \"version\": \"<string>\",\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"workspace_id\": \"<string>\",\n \"subdomain\": \"<string>\",\n \"envs\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"response": {
"id": "app-abc123def456",
"owner_id": "user-123456789012345678",
"owner_plan_id": 1,
"name": "API Simples",
"description": "I have a description :)",
"cluster": 1,
"status": "up",
"ram": 128,
"type": 2,
"language": "javascript",
"subdomain": "myapp.vertraweb.app",
"custom_domain": null,
"last_snapshot": "2026-03-20T19:58:00Z",
"main_file": "index.js",
"version": "recommended",
"start_command": null,
"build_command": null,
"offline_since": null,
"shield_cooldown": null,
"github": null,
"created_at": "2026-03-20T19:58:00Z",
"updated_at": "2026-03-20T19:58:00Z"
}
}
Applications
Create Application
Creates a new application with the provided configuration and files.
POST
/
v1
/
apps
Create Application
curl --request POST \
--url https://api.vertracloud.app/v1/apps \
--header 'Content-Type: application/json' \
--data '
{
"snapshot_id": "<string>",
"memory": "<string>",
"start": "<string>",
"build": "<string>",
"main": "<string>",
"version": "<string>",
"name": "<string>",
"description": "<string>",
"workspace_id": "<string>",
"subdomain": "<string>",
"envs": "<string>"
}
'import requests
url = "https://api.vertracloud.app/v1/apps"
payload = {
"snapshot_id": "<string>",
"memory": "<string>",
"start": "<string>",
"build": "<string>",
"main": "<string>",
"version": "<string>",
"name": "<string>",
"description": "<string>",
"workspace_id": "<string>",
"subdomain": "<string>",
"envs": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
snapshot_id: '<string>',
memory: '<string>',
start: '<string>',
build: '<string>',
main: '<string>',
version: '<string>',
name: '<string>',
description: '<string>',
workspace_id: '<string>',
subdomain: '<string>',
envs: '<string>'
})
};
fetch('https://api.vertracloud.app/v1/apps', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.vertracloud.app/v1/apps",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'snapshot_id' => '<string>',
'memory' => '<string>',
'start' => '<string>',
'build' => '<string>',
'main' => '<string>',
'version' => '<string>',
'name' => '<string>',
'description' => '<string>',
'workspace_id' => '<string>',
'subdomain' => '<string>',
'envs' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.vertracloud.app/v1/apps"
payload := strings.NewReader("{\n \"snapshot_id\": \"<string>\",\n \"memory\": \"<string>\",\n \"start\": \"<string>\",\n \"build\": \"<string>\",\n \"main\": \"<string>\",\n \"version\": \"<string>\",\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"workspace_id\": \"<string>\",\n \"subdomain\": \"<string>\",\n \"envs\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.vertracloud.app/v1/apps")
.header("Content-Type", "application/json")
.body("{\n \"snapshot_id\": \"<string>\",\n \"memory\": \"<string>\",\n \"start\": \"<string>\",\n \"build\": \"<string>\",\n \"main\": \"<string>\",\n \"version\": \"<string>\",\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"workspace_id\": \"<string>\",\n \"subdomain\": \"<string>\",\n \"envs\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vertracloud.app/v1/apps")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"snapshot_id\": \"<string>\",\n \"memory\": \"<string>\",\n \"start\": \"<string>\",\n \"build\": \"<string>\",\n \"main\": \"<string>\",\n \"version\": \"<string>\",\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"workspace_id\": \"<string>\",\n \"subdomain\": \"<string>\",\n \"envs\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"response": {
"id": "app-abc123def456",
"owner_id": "user-123456789012345678",
"owner_plan_id": 1,
"name": "API Simples",
"description": "I have a description :)",
"cluster": 1,
"status": "up",
"ram": 128,
"type": 2,
"language": "javascript",
"subdomain": "myapp.vertraweb.app",
"custom_domain": null,
"last_snapshot": "2026-03-20T19:58:00Z",
"main_file": "index.js",
"version": "recommended",
"start_command": null,
"build_command": null,
"offline_since": null,
"shield_cooldown": null,
"github": null,
"created_at": "2026-03-20T19:58:00Z",
"updated_at": "2026-03-20T19:58:00Z"
}
}
The application has two mutually exclusive sources — send exactly one of
file or
snapshot_id. Neither → SOURCE_REQUIRED; both → SOURCE_CONFLICT.
file
The ZIP file containing the application code (maximum size: 100 MB). Absent when the source is
snapshot_id.string
Alternative source to
file: the id of an application snapshot to create the app from. The
platform downloads the snapshot (which already carries the vertracloud.config) and builds the
app from it. Sent as a text field of the multipart body — same size limit as file (100 MB).string
The amount of RAM to allocate for the application in MB. Minimum 100 MB. Required with
file; with snapshot_id it is optional and falls back to the snapshot’s vertracloud.config. When a subdomain is
requested the value is raised to at least 512 MB automatically — web applications have their own
memory floor.string
The application startup command.
string
An optional build command, up to 512 characters (e.g.
npm run build). Runs after dependency
installation and before the application starts, in an isolated build environment — 2× the
application’s RAM (min 1,024 MB, max 4,096 MB) and 2× its vCPU (min 1, max 2), with a 10-minute
timeout. Available on every plan. See Update Application Configuration to change it later.string
The main file of the application. Required with
file; with snapshot_id it is optional and falls back to the snapshot’s vertracloud.config.string
Required with
file; with snapshot_id it falls back to the snapshot’s vertracloud.config. The application runtime version: recommended, latest, or a specific version supported by the
detected runtime (e.g. 22).string
required
The application display name. Maximum 50 characters.
string
An application description.
string
The workspace ID to associate with the application, if applicable.
string
The subdomain for the application (e.g.,
myapp). Whitespace is replaced with - and the value is
lowercased before validation; the accepted format is ^[a-z0-9-]+$. Send random to let the
platform pick one for you. Omit the field entirely to create a private application with no web
publishing — you can turn it on later with
Publish Application on the Web.Requires plan support for web publishing.string
A JSON string containing an array of environment variables, each with
key, value and an
optional note. Maximum key length 255, maximum value length 3072, maximum note length 50.Response
object
The details of the created application.
Show Toggle object
Show Toggle object
string
The application ID.
string
The application owner ID.
integer
The owner’s plan ID.
string
The application name.
string
The application description.
integer
The application cluster ID.
string
The application status:
up, or down when dependency installation or the build command
failed. A failed install or build still creates the application — stopped, with the output in
its logs — so you can fix the files and start it again without re-uploading.integer
The application RAM in MB.
integer
The application type.
string
The application programming language (e.g.,
javascript).string | null
The application subdomain, if applicable.
string | null
The custom domain of the application, if applicable.
string
The timestamp when the application was created.
string
The timestamp when the application was last updated.
string | null
The timestamp of the application’s last snapshot.
string
The main file of the application.
string
The runtime version (e.g.,
recommended or latest).string | null
The startup command for the application, if specified.
string | null
The build command, if specified. Runs after dependency installation and before the
application starts.
string | null
The timestamp since the application went offline, if applicable.
object | null
Present while Vertra Shield has paused the application. Includes
until (the cooldown end time),
reason (burst or rate_limit), and direction (in or out); null when no cooldown is active.object | null
Linked GitHub repository (
repo_owner, repo_name) when auto-deploy is connected; null
when the app was created from a zip or snapshot. The webhook URL is not included — use
GET /v1/apps/{id}/deploys/webhook for that.{
"response": {
"id": "app-abc123def456",
"owner_id": "user-123456789012345678",
"owner_plan_id": 1,
"name": "API Simples",
"description": "I have a description :)",
"cluster": 1,
"status": "up",
"ram": 128,
"type": 2,
"language": "javascript",
"subdomain": "myapp.vertraweb.app",
"custom_domain": null,
"last_snapshot": "2026-03-20T19:58:00Z",
"main_file": "index.js",
"version": "recommended",
"start_command": null,
"build_command": null,
"offline_since": null,
"shield_cooldown": null,
"github": null,
"created_at": "2026-03-20T19:58:00Z",
"updated_at": "2026-03-20T19:58:00Z"
}
}
Error Responses
string
The error code indicating the reason for the failure. Possible values:
VALIDATION_ERROR: The multipart body failed validation (400). The response also carriesmessageandpathpointing at the offending field.USER_NOT_FOUND: The request is not authenticated (403), or the owner’s limits could not be resolved (404).MAX_APPS_REACHED: The plan’s application limit has been reached (403).INVALID_ZIP: The uploaded file is not a readable ZIP (truncated or corrupted) (400).MAIN_FILE_NOT_FOUND: The file named inmaindoes not exist inside the ZIP (400).ZIP_TOO_SMALL: The uploaded file is smaller than 100 bytes (400).FILE_TOO_LARGE: The uploaded file exceeds the 100 MB limit (400).SOURCE_REQUIRED: Neitherfilenorsnapshot_idwas sent (400).SOURCE_CONFLICT: Bothfileandsnapshot_idwere sent (400).SNAPSHOT_NOT_FOUND: Thesnapshot_iddoesn’t exist or doesn’t belong to the caller (404).SNAPSHOT_TYPE_MISMATCH: The snapshot is a database snapshot, not an application one (400).SNAPSHOT_TOO_LARGE: The snapshot exceeds the same 100 MB creation ceiling asfile(400).MEMORY_REQUIRED:memorywas omitted and the snapshot’svertracloud.confighas no usableMEMORY(400).FREE_PLAN_SUSPENDED: The owner is on the Free plan, which can’t create new applications (403).FREE_PLAN_NO_WEB_PUBLISH: Asubdomainwas requested but the owner’s plan does not include web publishing (403).INVALID_MEMORY_FORMAT:memoryis not a number (400).MEMORY_MUST_BE_INTEGER:memoryis not an integer (400).MEMORY_BELOW_MINIMUM:memoryis below the minimum for the application type (400).MEMORY_LIMIT_EXCEEDED: The requested memory exceeds the memory still available on the plan (400).SUBDOMAIN_TAKEN: Another application already uses that subdomain (409).SUBDOMAIN_FORBIDDEN: The requested subdomain is on the platform’s reserved list (400).USER_LIMITS_NOT_FOUND: The owner’s limits record could not be loaded (404).INVALID_LANGUAGE: The application language could not be determined (500).INTERNAL_SERVER_ERROR: The application was created but could not be read back (500).DEPLOY_RATE_LIMITED: The account’s hourly deploy budget for its plan was reached (429). See API Reference Introduction.INTERNAL_SERVER_ERROR: Unexpected failure (500).
string
A descriptive message providing additional details about the error. Present on
VALIDATION_ERROR.{
"code": "VALIDATION_ERROR",
"message": "Main file is required",
"path": "main"
}
{
"code": "MAIN_FILE_NOT_FOUND"
}
{
"code": "FREE_PLAN_NO_WEB_PUBLISH"
}
An application created without
subdomain stays private. You can turn web publishing on later
with Publish Application on the Web, and off again
with the same route.