# Deploy TypeDB via the Cloud API

This guide will walk you through the creation of a script to automate deployment of a TypeDB cluster on TypeDB Cloud.

We’re going to build a script that authenticates with the API, deploys a TypeDB cluster, and retrieves its status in a polling loop until it’s ready to receive incoming connections.

## [](#_before_you_start)Before you start

1.  Sign in to your TypeDB Cloud account at [https://cloud.typedb.com](https://cloud.typedb.com).
    
2.  In [Team settings - API tokens](https://cloud.typedb.com/?team_action=/settings#api-tokens), create a new API token with `Write` access.
    

Make sure to save the client secret somewhere safe - you will only see it when you first generate the token, and will be unable to use the token without it.

## [](#_overview)Overview

We will write a script to deploy TypeDB, which will:

1.  Generate an API access token
    
2.  Use this token to launch a single-node TypeDB cluster
    
3.  Wait for the cluster to become ready to receive incoming connections
    

Here’s the full script. In the following sections we’ll break down what each part of the script does.

*   Bash
    
*   Python
    
*   Node.js
    

```bash
#!/usr/bin/env bash

set -e

# Check if the required environment variables are set
if [ -z "$TYPEDB_CLOUD_CLIENT_ID" ] || [ -z "$TYPEDB_CLOUD_CLIENT_SECRET" ]; then
    echo "Error: TYPEDB_CLOUD_CLIENT_ID and TYPEDB_CLOUD_CLIENT_SECRET environment variables must be set"
    exit 1
fi

# Check if the required arguments are provided
if [[ "$#" -ne 5 ]]; then
    echo "Usage: $0 <team_id> <space_id> <provider> <region> <cluster_id>"
    exit 1
fi

TEAM_ID=$1
SPACE_ID=$2
PROVIDER=$3
REGION=$4
CLUSTER_ID=$5

# Get a short-lived access token
TYPEDB_CLOUD_ACCESS_TOKEN=$(
  curl --request POST \
    --url https://cloud.typedb.com/api/v1/auth \
    --header "Authorization: Basic $TYPEDB_CLOUD_CLIENT_ID:$TYPEDB_CLOUD_CLIENT_SECRET"
)

CLUSTER_CONFIG="{
  \"id\":\"$CLUSTER_ID\",
  \"serverCount\":1,
  \"storageSizeGB\":10,
  \"provider\":\"$PROVIDER\",
  \"region\":\"$REGION\",
  \"isFree\":true,
  \"machineType\":\"c2d-highcpu-2\",
  \"storageType\":\"standard-rwo\",
  \"version\":\"latest\"
}"

# Deploy the cluster
CLUSTER_RES=$(curl --request POST \
  --url "https://cloud.typedb.com/api/team/$TEAM_ID/spaces/$SPACE_ID/clusters/deploy" \
  --header "Authorization: Bearer $TYPEDB_CLOUD_ACCESS_TOKEN" \
  --json "$CLUSTER_CONFIG")

# Wait for the cluster to be up and running
while [[ $(echo $CLUSTER_RES | jq -r '.status') != 'running' ]]; do
  if [[ $(echo $CLUSTER_RES | jq -r '.message') != null ]]; then
    echo "Error: $(echo $CLUSTER_RES | jq -r '.message')"
    exit 1
  fi
  echo
  echo "Sleeping..."
  echo
  sleep 15
  CLUSTER_RES=$(curl --request GET \
    --url https://cloud.typedb.com/api/team/$TEAM_ID/spaces/$SPACE_ID/clusters/$CLUSTER_ID \
    --header "Authorization: Bearer $TYPEDB_CLOUD_ACCESS_TOKEN")
done
```

```python
import requests
import os
import sys
import time

def main():
    client_id = os.getenv("TYPEDB_CLOUD_CLIENT_ID")
    client_secret = os.getenv("TYPEDB_CLOUD_CLIENT_SECRET")

    if client_id is None or client_secret is None:
        print("TYPEDB_CLOUD_CLIENT_ID and TYPEDB_CLOUD_CLIENT_SECRET environment variables must be set")
        sys.exit(1)

    if len(sys.argv) != 5:
        print("Usage: python main.py <team_id> <space_id> <region> <cluster_id>")
        sys.exit(1)

    team_id = sys.argv[1]
    space_id = sys.argv[2]
    region = sys.argv[3]
    cluster_id = sys.argv[4]

    access_token = get_access_token(client_id, client_secret)

    cluster_config = {
        "id": cluster_id,
        "serverCount": 1,
        "storageSizeGB": 10,
        "provider": "gcp",
        "region": region,
        "isFree": True,
        "machineType": "c2d-highcpu-2",
        "storageType": "standard-rwo",
        "version": "latest"
    }

    response = deploy_cluster(access_token, team_id, space_id, cluster_config)

    while response["status"] != "running":
        print("\nSleeping...\n")
        time.sleep(15)
        response = get_cluster(access_token, team_id, space_id, cluster_id)

def get_access_token(client_id, client_secret):
    url = "https://cloud.typedb.com/api/auth"

    headers = {
        "Authorization": f"Basic {client_id}:{client_secret}"
    }

    response = requests.post(url, headers=headers)
    if response.status_code >= 400: print(response.text)
    response.raise_for_status()
    return response.text

def deploy_cluster(access_token, team_id, space_id, cluster_config):
    url = f"https://cloud.typedb.com/api/team/{team_id}/spaces/{space_id}/clusters/deploy"

    headers = {
        "Authorization": f"Bearer {access_token}"
    }

    response = requests.post(url, headers=headers, json=cluster_config)
    if response.status_code >= 400: print(response.text)
    response.raise_for_status()

    return response.json()

def get_cluster(access_token, team_id, space_id, cluster_id):
    url = f"https://cloud.typedb.com/api/team/{team_id}/spaces/{space_id}/clusters/{cluster_id}"

    headers = {
        "Authorization": f"Bearer {access_token}"
    }

    response = requests.get(url, headers=headers)
    if response.status_code >= 400: print(response.text)
    response.raise_for_status()

    return response.json()

if __name__ == "__main__":
    main()
```

```javascript
main();

async function main() {
    const clientId = process.env.TYPEDB_CLOUD_CLIENT_ID;
    const clientSecret = process.env.TYPEDB_CLOUD_CLIENT_SECRET;

    if (!clientId || !clientSecret) {
        console.error("TYPEDB_CLOUD_CLIENT_ID or TYPEDB_CLOUD_CLIENT_SECRET not found");
        process.exit(1);
    }

    if (process.argv.length != 6) {
        console.error("Usage: node deploy.ts <team_id> <space_id> <region> <cluster_id>");
        process.exit(1);
    }

    const teamId = process.argv[2];
    const spaceId = process.argv[3];
    const region = process.argv[4];
    const clusterId = process.argv[5];

    const accessToken = await getAccessToken(clientId, clientSecret);

    const clusterConfig = {
        id: clusterId,
        serverCount: 1,
        storageSizeGB: 10,
        provider: "gcp",
        region: region,
        isFree: true,
        machineType: "c2d-highcpu-2",
        storageType: "standard-rwo",
        version: "latest"
    };

    let response = await deployCluster(accessToken, teamId, spaceId, clusterConfig);

    while (response.status != "running") {
        console.log("\nSleeping...\n");
        await new Promise((resolve) => { setTimeout(resolve, 15_000); });
        response = await getCluster(accessToken, teamId, spaceId, clusterId);
    }
}

async function getAccessToken(clientId, clientSecret) {
    const url = "https://cloud.typedb.com/api/v1/auth";
    const request = new Request(
        url, {
            method: "POST",
            headers: {Authorization: `Basic ${clientId}:${clientSecret}`}
        }
    );

    return fetch(request).then(async res => {
        if (!res.ok) throw Error(await res.text());
        return res.text();
    });
}

async function deployCluster(accessToken, teamId, spaceId, clusterConfig) {
    const url = `https://cloud.typedb.com/api/v1/team/${teamId}/spaces/${spaceId}/clusters/deploy`;
    const request = new Request(
        url, {
            method: "POST",
            headers: {
                Authorization: `Bearer ${accessToken}`,
                Accept: 'application/json',
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(clusterConfig),
        },
    );

    return fetch(request).then(async res => {
        if (!res.ok) throw Error(await res.text());
        return res.json();
    });
}

async function getCluster(accessToken, teamId, spaceId, clusterId) {
    const url = `https://cloud.typedb.com/api/v1/team/${teamId}/spaces/${spaceId}/clusters/${clusterId}`;
    const request = new Request(
        url, {
            method: "GET",
            headers: {Authorization: `Bearer ${accessToken}`},
        },
    );

    return fetch(request).then(async res => {
        if (!res.ok) throw Error(await res.text());
        return res.json();
    });
}
```

## [](#_script_breakdown)Script breakdown

### [](#_1_arguments)1\. Arguments

*   Bash
    
*   Python
    
*   Node.js
    

```bash
if [ -z "$TYPEDB_CLOUD_CLIENT_ID" ] || [ -z "$TYPEDB_CLOUD_CLIENT_SECRET" ]; then
    echo "Error: TYPEDB_CLOUD_CLIENT_ID and TYPEDB_CLOUD_CLIENT_SECRET environment variables must be set"
    exit 1
fi

if [[ "$#" -ne 4 ]]; then
    echo "Usage: $0 <team_id> <space_id> <region> <cluster_id>"
    exit 1
fi

TEAM_ID=$1
SPACE_ID=$2
REGION=$3
CLUSTER_ID=$4
```

```python
client_id = os.getenv("TYPEDB_CLOUD_CLIENT_ID")
client_secret = os.getenv("TYPEDB_CLOUD_CLIENT_SECRET")

if client_id is None or client_secret is None:
    print("TYPEDB_CLOUD_CLIENT_ID and TYPEDB_CLOUD_CLIENT_SECRET environment variables must be set")
    sys.exit(1)

if len(sys.argv) != 5:
    print("Usage: python main.py <team_id> <space_id> <region> <cluster_id>")
    sys.exit(1)

team_id = sys.argv[1]
space_id = sys.argv[2]
region = sys.argv[3]
cluster_id = sys.argv[4]
```

```javascript
const clientId = process.env.TYPEDB_CLOUD_CLIENT_ID;
const clientSecret = process.env.TYPEDB_CLOUD_CLIENT_SECRET;

if (!clientId || !clientSecret) {
    console.error("TYPEDB_CLOUD_CLIENT_ID or TYPEDB_CLOUD_CLIENT_SECRET not found");
    process.exit(1);
}

if (process.argv.length != 6) {
    console.error("Usage: node deploy.ts <team_id> <space_id> <region> <cluster_id>");
    process.exit(1);
}

const teamId = process.argv[2];
const spaceId = process.argv[3];
const region = process.argv[4];
const clusterId = process.argv[5];
```

We use environment variables for the Client ID and Client Secret of the API token, and take our other configurable options as command-line arguments.

### [](#_2_token_exchange)2\. Token exchange

*   Bash
    
*   Python
    
*   Node.js
    

```bash
TYPEDB_CLOUD_ACCESS_TOKEN=$(
  curl --request POST \
    --url https://cloud.typedb.com/api/v1/auth \
    --header "Authorization: Basic $TYPEDB_CLOUD_CLIENT_ID:$TYPEDB_CLOUD_CLIENT_SECRET"
)
```

```python
def get_access_token(client_id, client_secret):
    url = "https://cloud.typedb.com/api/v1/auth"

    headers = {
        "Authorization": f"Basic {client_id}:{client_secret}"
    }

    response = requests.post(url, headers=headers)
    if response.status_code >= 400: print(response.text)
    response.raise_for_status()
    return response.text
```

```javascript
async function getAccessToken(clientId, clientSecret) {
    const url = "https://cloud.typedb.com/api/v1/auth";
    const request = new Request(
        url, {
            method: "POST",
            headers: {Authorization: `Basic ${clientId}:${clientSecret}`}
        }
    );

    return fetch(request).then(async res => {
        if (!res.ok) throw Error(await res.text());
        return res.text();
    });
}
```

We’ll need an access token. To get it we post to `[https://cloud.typedb.com/api/v1/auth](https://cloud.typedb.com/api/v1/auth)` with the long-lived client ID and secret.

### [](#_3_cluster_configuration)3\. Cluster configuration

*   Bash
    
*   Python
    
*   Node.js
    

```bash
CLUSTER_CONFIG="{
  \"id\":\"$CLUSTER_ID\",
  \"serverCount\":1,
  \"storageSizeGB\":10,
  \"provider\":\"gcp\",
  \"region\":\"$REGION\",
  \"isFree\":true,
  \"machineType\":\"c2d-highcpu-2\",
  \"storageType\":\"standard-rwo\",
  \"version\":\"latest\"
}"
```

```python
cluster_config = {
    "id": cluster_id,
    "serverCount": 1,
    "storageSizeGB": 10,
    "provider": "gcp",
    "region": region,
    "isFree": True,
    "machineType": "c2d-highcpu-2",
    "storageType": "standard-rwo",
    "version": "latest"
}
```

```javascript
const clusterConfig = {
    id: clusterId,
    serverCount: 1,
    storageSizeGB: 10,
    provider: "gcp",
    region: region,
    isFree: true,
    machineType: "c2d-highcpu-2",
    storageType: "standard-rwo",
    version: "latest"
};
```

This JSON object defines how your cluster will be deployed. The parameters could be redefined in the script, or adjusted to be arguments to suit your needs. In this case, we’ve provided preset values for all parameters except ID and region.

See the [API reference](../../../reference/cloud-http-api/index.md) for more details on cluster configuration.

### [](#_4_deploying_typedb)4\. Deploying TypeDB

*   Bash
    
*   Python
    
*   Node.js
    

```bash
CLUSTER_RES=$(
  curl --request POST \
    --url "https://cloud.typedb.com/api/v1/team/$TEAM_ID/spaces/$SPACE_ID/clusters/deploy" \
    --header "Authorization: Bearer $TYPEDB_CLOUD_ACCESS_TOKEN" \
    --json "$CLUSTER_CONFIG"
)
```

```python
def deploy_cluster(access_token, team_id, space_id, cluster_config):
    url = f"https://cloud.typedb.com/api/v1/team/{team_id}/spaces/{space_id}/clusters/deploy"

    headers = {
        "Authorization": f"Bearer {access_token}"
    }

    response = requests.post(url, headers=headers, json=cluster_config)
    if response.status_code >= 400: print(response.text)
    response.raise_for_status()

    return response.json()
```

```javascript
async function deployCluster(accessToken, teamId, spaceId, clusterConfig) {
    const url = `https://cloud.typedb.com/api/v1/team/${teamId}/spaces/${spaceId}/clusters/deploy`;
    const request = new Request(
        url, {
            method: "POST",
            headers: {
                Authorization: `Bearer ${accessToken}`,
                Accept: 'application/json',
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(clusterConfig),
        },
    );

    return fetch(request).then(async res => {
        if (!res.ok) throw Error(await res.text());
        return res.json();
    });
}
```

We use the cluster config and the access token we acquired previously to actually deploy the cluster. We store the response for use in the next step.

### [](#_5_waiting_for_the_cluster_to_be_ready)5\. Waiting for the cluster to be ready

*   Bash
    
*   Python
    
*   Node.js
    

```bash
while [[ $(echo $CLUSTER_RES | jq -r '.status') != 'running' ]]; do
  if [[ $(echo $CLUSTER_RES | jq -r '.message') != null ]]; then
    echo "Error: $(echo $CLUSTER_RES | jq -r '.message')"
    exit 1
  fi
  echo
  echo "Sleeping..."
  echo
  sleep 15
  CLUSTER_RES=$(curl --request GET \
    --url https://cloud.typedb.com/api/v1/team/$TEAM_ID/spaces/$SPACE_ID/clusters/$CLUSTER_ID \
    --header "Authorization: Bearer $TYPEDB_CLOUD_ACCESS_TOKEN")
done
```

```python
while response["status"] != "running":
    print("\nSleeping...\n")
    time.sleep(15)
    response = get_cluster(access_token, team_id, space_id, cluster_id)

def get_cluster(access_token, team_id, space_id, cluster_id):
    url = f"https://cloud.typedb.com/api/v1/team/{team_id}/spaces/{space_id}/clusters/{cluster_id}"

    headers = {
        "Authorization": f"Bearer {access_token}"
    }

    response = requests.get(url, headers=headers)
    if response.status_code >= 400: print(response.text)
    response.raise_for_status()

    return response.json()
```

```javascript
while (response.status != "running") {
    console.log("\nSleeping...\n");
    await new Promise((resolve) => { setTimeout(resolve, 15_000); });
    response = await getCluster(accessToken, teamId, spaceId, clusterId);
}

async function getCluster(accessToken, teamId, spaceId, clusterId) {
    const url = `https://cloud.typedb.com/api/v1/team/${teamId}/spaces/${spaceId}/clusters/${clusterId}`;
    const request = new Request(
        url, {
            method: "GET",
            headers: {Authorization: `Bearer ${accessToken}`},
        },
    );

    return fetch(request).then(async res => {
        if (!res.ok) throw Error(await res.text());
        return res.json();
    });
}
```

We wait for the cluster to be ready to receive incoming connections by polling the cluster’s status until it’s running. If we encounter an error at any point (either during the initial deployment, or when subsequently getting the cluster to check its status) we print the error and exit.

## [](#_example_usage)Example usage

1.  Export your credentials:
    
    ```bash
    export TYPEDB_CLOUD_CLIENT_ID=myClientID
    export TYPEDB_CLOUD_CLIENT_SECRET=mySecret
    ```
    
2.  Run the script:
    
    *   Bash
        
    *   Python
        
    *   Node.js
        
    
    ```bash
    ./deploy.sh my-team my-space gcp europe-west2 api-cluster
    ```
    
    ```bash
    python main.py my-team my-space gcp europe-west2 api-cluster
    ```
    
    ```bash
    node deploy.js my-team my-space gcp europe-west2 api-cluster
    ```
    

If successful, TypeDB Cloud will deploy your cluster, and the script will poll it until it’s ready to receive incoming connections.

## [](#_conclusion)Conclusion

This guide has shown you how to set up a script to deploy TypeDB through the Cloud API.

Similar approaches can be used for other common actions, such as pausing or resuming your clusters when not in use.

## [](#_next_steps)Next steps

[TypeDB Cloud](https://cloud.typedb.com)

Head back to TypeDB Cloud to keep exploring there.

[API reference](../../../reference/cloud-http-api/index.md)

View the API reference for more detail on what you can do with it.

[Integrations](../index.md) [Use TypeDB in GitHub Actions](../use-github-actions/index.md)

[Edit on GitHub](https://github.com/typedb/typedb-docs/edit/3.x-development/guides/modules/ROOT/pages/integrations/deploy-through-api.adoc) Edit this page on GitHub.