# Get Started

This guide helps you make your first API call to TiDB Cloud API. You'll learn how to authenticate a request, build a request, and interpret the response. The [List all accessible projects](#tag/Project/operation/ListProjects) endpoint is used in this guide as an example.

## Prerequisites

To complete this guide, you need to perform the following tasks:

- Create a [TiDB Cloud account](https://tidbcloud.com/free-trial)
- Install [curl](https://curl.se/)

## Step 1. Create an API key

To create an API key, log in to your TiDB Cloud console. Navigate to the [**API Keys**](https://tidbcloud.com/org-settings/api-keys) page, and create an API key.

An API key contains a public key and a private key. Copy and save them in a secure location. You will need to use the API key later in this guide.

For more details about creating an API key, refer to [API Key Management](#section/Authentication/API-Key-Management).

## Step 2. Make your first API call

### Build an API call

TiDB Cloud API call consists of the following components:

- **A host.** The host for TiDB Cloud API is <https://api.tidbcloud.com>.
- **An API Key**. The public key and the private key are required for authentication.
- **A request.** When submitting data to a resource via `POST`, `PATCH`, or `PUT`, you must submit your payload in JSON.

In this guide, you call the [List all accessible projects](#tag/Project/operation/ListProjects) endpoint. For the detailed description of the endpoint, see the [API reference](#tag/Project/operation/ListProjects).

### Call an API endpoint

To get all projects in your organization, run the following command in your terminal. Remember to change `YOUR_PUBLIC_KEY` to your public key and `YOUR_PRIVATE_KEY` to your private key.

```shell
curl --digest \
  --user 'YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY' \
  --request GET \
  --url https://api.tidbcloud.com/api/v1beta/projects
```

## Step 3. Check the response

After making the API call, if the status code in response is `200` and you see details about all the projects in your organization, your request is successful. Here is an example of a successful response.

```log
{
  "items": [
    {
      "id": "{project_id}",
      "org_id": "{org_id}",
      "name": "MyProject",
      "cluster_count": 3,
      "user_count": 1,
      "create_timestamp": "1652407748"
    }
  ],
  "total": 1
}
```

If your API call is not successful, you will receive a status code other than `200` and the response looks similar to the following example. To troubleshoot the failed call, you can check the `message` in the response.

```log
{
  "code": 49900001,
  "message": "public_key not found",
  "details": []
}
```

## Code samples

This section walks you through the quickest way to get started with TiDB Cloud API using programming languages. In these examples, you will learn how to use Python to create a cluster, backup and restore data, and scale out a cluster.

You can view the [full code examples](https://github.com/tidbcloud/tidbcloud-api-samples) of Python and Golang on GitHub or clone the repository to your local machine.

```git
git clone https://github.com/tidbcloud/tidbcloud-api-samples.git
```

### Create and connect to a TiDB cluster

The following code examples show how to create a TiDB cluster and connect to the cluster. The whole process takes five steps:

1. Get all projects.
2. Get the cloud providers, regions and specifications.
3. Create a cluster in your specified project.
4. Get the new cluster information.
5. Connect to the cluster using a MySQL client.

#### Step 1: Get all projects

Before you create a cluster, you need to get the ID of the project that you want to create a cluster in.

To view the information of all available projects, you can use the [List all accessible projects](#tag/Project/operation/ListProjects) endpoint.

```python
import requests
from requests.auth import HTTPDigestAuth

HOST = "https://api.tidbcloud.com"


def get_all_projects(public_key: str, private_key: str) -> dict:
    """
    Get all projects
    :param public_key: Your public key
    :param private_key: Your private key
    :return: Projects detail
    """
    url = f"{HOST}/api/v1beta/projects"
    resp = requests.get(url=url, auth=HTTPDigestAuth(public_key, private_key))
    if resp.status_code != 200:
        print(f"request invalid, code : {resp.status_code}, message : {resp.text}")
        raise Exception(f"request invalid, code : {resp.status_code}, message : {resp.text}")
    return resp.json()


if __name__ == "__main__":
    # Replace YOUR_PUBLIC_KEY and YOUR_PRIVATE_KEY
    project = get_all_projects("{YOUR_PUBLIC_KEY}", "{YOUR_PRIVATE_KEY}")
    print(project)
```

For more details about the request and response, see [List all accessible projects](#tag/Project/operation/ListProjects).

#### Step 2: Get the cloud providers, regions and specifications

Before you create a cluster, you need to get the list of available cloud providers, regions, and specifications.

```python
import requests
from requests.auth import HTTPDigestAuth

HOST = "https://api.tidbcloud.com"


def get_provider_regions_specifications(public_key: str, private_key: str) -> dict:
    """
    Get cloud providers, regions and available specifications.
    :param public_key: Your public key
    :param private_key: Your private key
    :return: List the cloud providers, regions and available specifications.
    """
    url = f"{HOST}/api/v1beta/clusters/provider/regions"
    resp = requests.get(url=url, auth=HTTPDigestAuth(public_key, private_key))
    if resp.status_code != 200:
        print(f"request invalid, code : {resp.status_code}, message : {resp.text}")
        raise Exception(f"request invalid, code : {resp.status_code}, message : {resp.text}")
    return resp.json()


if __name__ == "__main__":
    # Replace YOUR_PUBLIC_KEY and YOUR_PRIVATE_KEY
    provider_regions_specifications = get_provider_regions_specifications("{YOUR_PUBLIC_KEY}", "{YOUR_PRIVATE_KEY}")
    print(provider_regions_specifications)
```

For more details about the request and response, see [List the cloud providers, regions and available specifications](#tag/Cluster/operation/ListProviderRegions).

#### Step 3: Create a cluster in your specified project and cloud provider

The following example uses the [Create a cluster](#tag/Cluster/operation/CreateCluster) endpoint to create a TiDB Cloud Dedicated cluster. A configuration example is provided in the code; you can replace the parameters using the information you get in the previous two steps.

```python
import requests
import time
import json
from requests.auth import HTTPDigestAuth

HOST = "https://api.tidbcloud.com"


def create_dedicated_cluster(public_key: str, private_key: str, project_id: str) -> dict:
    """
    Create a dedicated cluster in your specified project.
    `data_config` below is a demo. You should fill in the field according to
    your own situation
    :param public_key: Your public key
    :param private_key: Your private key
    :param project_id: The project id
    :return: Dedicated cluster id
    """
    url = f"{HOST}/api/v1beta/projects/{project_id}/clusters"
    ts = int(time.time())
    data_config = \
        {
            "name": f"tidbcloud-sample-{ts}",
            "cluster_type": "DEDICATED",
            "cloud_provider": "AWS",
            "region": "us-west-2",
            "config":
                {
                    "root_password": "input_your_password",
                    "port": 4000,
                    "components":
                        {
                            "tidb":
                                {
                                    "node_size": "8C16G",
                                    "node_quantity": 1
                                },
                            "tikv":
                                {"node_size": "8C32G",
                                 "storage_size_gib": 500,
                                 "node_quantity": 3
                                 }
                        },
                    "ip_access_list":
                        [
                            {
                                "cidr": "0.0.0.0/0",
                                "description": "Allow Access from Anywhere."
                            }
                        ]

                }
        }
    data_config_json = json.dumps(data_config)
    resp = requests.post(url=url,
                         auth=HTTPDigestAuth(public_key, private_key),
                         data=data_config_json)
    if resp.status_code != 200:
        print(f"request invalid, code : {resp.status_code}, message : {resp.text}")
        raise Exception(f"request invalid, code : {resp.status_code}, message : {resp.text}")
    return resp.json()


if __name__ == "__main__":
    # Replace YOUR_PUBLIC_KEY, YOUR_PRIVATE_KEY and YOUR_PROJECT_ID
    cluster = create_dedicated_cluster("{YOUR_PUBLIC_KEY}", "{YOUR_PRIVATE_KEY}", "{YOUR_PROJECT_ID}")
    print(cluster)
```

This request returns the ID of the cluster that you just created. For more details about the request and response, see [Create a cluster](#tag/Cluster/operation/CreateCluster).

#### Step 4: Get the new cluster information

After you successfully create a cluster, you can use the [Get cluster by ID](#tag/Cluster/operation/GetCluster) endpoint to get the information of the cluster.

```python
import requests
from requests.auth import HTTPDigestAuth

HOST = "https://api.tidbcloud.com"


def get_cluster_by_id(public_key: str, private_key: str, project_id: str, cluster_id: str) -> dict:
    """
    Get the cluster detail.
    You will get `connection_strings` from the response after the cluster's status is`AVAILABLE`.
    Then, you can connect to TiDB using the default user, host, and port in `connection_strings`
    :param public_key: Your public key
    :param private_key: Your private key
    :param project_id: The project id
    :param cluster_id: The cluster id
    :return: The cluster detail
    """
    url = f"{HOST}/api/v1beta/projects/{project_id}/clusters/{cluster_id}"
    resp = requests.get(url=url,
                        auth=HTTPDigestAuth(public_key, private_key))
    if resp.status_code != 200:
        print(f"request invalid, code : {resp.status_code}, message : {resp.text}")
        raise Exception(f"request invalid, code : {resp.status_code}, message : {resp.text}")
    return resp.json()


if __name__ == "__main__":
    # Replace YOUR_PUBLIC_KEY, YOUR_PRIVATE_KEY, YOUR_PROJECT_ID and YOUR_CLUSTER_ID
    cluster = get_cluster_by_id("{YOUR_PUBLIC_KEY}", "{YOUR_PRIVATE_KEY}", "{YOUR_PROJECT_ID}",
                                       "{YOUR_CLUSTER_ID}")
    print(cluster)
```

In the response, you can see the `connection_strings` field, which will be used later for connecting to the TiDB cluster. However, if your cluster status is `CREATING`, the `connection_strings` field might be empty. In such cases, you need to wait a while until the cluster status becomes `AVAILABLE` so that you can move on to the next step.

For more details about the request and response, see [Get a cluster by ID](#tag/Cluster/operation/GetCluster).

#### Step 5: Connect to the cluster using a MySQL client

After the cluster becomes `AVAILABLE`, you can get the connection strings. With the connection strings, you can connect to the cluster using a MySQL client.

The connection strings contain three fields:

- `default_user`, the username you use to connect to TiDB.
- `standard` connection string. In this guide, you'll use the `standard` connection.
- `vpc_peering` connection string.

The `standard` connection string contains a `host` and a `port`. In the following command, replace `${default_user}` and `${host}` with the actual values in the connection strings. Run the command to connect to the TiDB cluster.

```shell
mysql --connect-timeout 15 -u ${default_user} -h ${host} -P 4000 -D test -p
```

For more details on connection, see [Connect to TiDB Cluster](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster).

### Manage backups for your clusters

The following example shows how to create a manual backup and restore the last backup data to a new cluster.

#### Step 1: Create a manual backup

To create a manual backup, you can use the [Create a backup for a cluster](#tag/Backup/operation/CreateBackup) endpoint.

```python
import requests
import json
import datetime
from requests.auth import HTTPDigestAuth

HOST = "https://api.tidbcloud.com"


def create_manual_backup(public_key: str, private_key: str, project_id: str, cluster_id: str) -> dict:
    """
    Create manual backup
    `data_for_backup` below is a demo. You should fill in the field according to
    your own situation
    :param public_key: Your public key
    :param private_key: Your private key
    :param project_id: The project id
    :param cluster_id: The dedicated cluster id
    :return: The backup id
    """
    url = f"{HOST}/api/v1beta/projects/{project_id}/clusters/{cluster_id}/backups"
    cur_date = datetime.datetime.now().strftime("%Y-%m-%d")
    data_for_backup = {"name": f"tidbcloud-backup-{cur_date}", "description": f"tidbcloud-backup-{cur_date}"}
    data_for_backup_json = json.dumps(data_for_backup)
    resp = requests.post(url=url,
                         data=data_for_backup_json,
                         auth=HTTPDigestAuth(public_key, private_key))
    if resp.status_code != 200:
        print(f"request invalid, code : {resp.status_code}, message : {resp.text}")
        raise Exception(f"request invalid, code : {resp.status_code}, message : {resp.text}")
    return resp.json()


if __name__ == "__main__":
    # Replace YOUR_PUBLIC_KEY, YOUR_PRIVATE_KEY, YOUR_PROJECT_ID and YOUR_CLUSTER_ID
    backup = create_manual_backup("{YOUR_PUBLIC_KEY}", "{YOUR_PRIVATE_KEY}", "{YOUR_PROJECT_ID}",
                                  "{YOUR_CLUSTER_ID}")
    print(backup)
```

#### Step 2: Restore the last backup data to a new cluster

To restore the last backup data to a new cluster, you can use the [Create a restore task](#tag/Restore/operation/CreateRestoreTask) endpoint.

```python
import requests
import json
import datetime
from requests.auth import HTTPDigestAuth

HOST = "https://api.tidbcloud.com"


def create_restore_task(public_key: str, private_key: str, project_id: str, back_up_id: str) -> dict:
    """
    Create restore task
    `data_for_restore` below is a demo. You should fill in the field according to
    your own situation
    :param private_key: Your public key
    :param public_key: Your private key
    :param project_id: The project id
    :param back_up_id: The backup id
    :return: The restore task id
    """
    url = f"{HOST}/api/v1beta/projects/{project_id}/restores"
    cur_date = datetime.datetime.now().strftime("%Y-%m-%d")
    data_for_restore = \
        {
            "backup_id": f"{back_up_id}",
            "name": f"tidbcloud-restore-{cur_date}",
            "config":
                {
                    "root_password": "input_your_password",
                    "port": 4000,
                    "components":
                        {
                            "tidb":
                                {
                                    "node_size": "8C16G",
                                    "node_quantity": 1
                                },
                            "tikv":
                                {
                                    "node_size": "8C32G",
                                    "storage_size_gib": 500,
                                    "node_quantity": 3
                                }
                        },
                    "ip_access_list":
                        [
                            {
                                "cidr": "0.0.0.0/0",
                                "description": "Allow Access from Anywhere."
                            }
                        ]

                }
        }
    data_for_restore_json = json.dumps(data_for_restore)
    resp = requests.post(url=url,
                         auth=HTTPDigestAuth(public_key, private_key),
                         data=data_for_restore_json)
    if resp.status_code != 200:
        print(f"request invalid, code : {resp.status_code}, message : {resp.text}")
        raise Exception(f"request invalid, code : {resp.status_code}, message : {resp.text}")
    return resp.json()


if __name__ == "__main__":
    # Replace YOUR_PUBLIC_KEY, YOUR_PRIVATE_KEY, YOUR_PROJECT_ID and YOUR_BACKUP_ID
    restore = create_restore_task("{YOUR_PUBLIC_KEY}", "{YOUR_PRIVATE_KEY}", "{YOUR_PROJECT_ID}",
                                  "{YOUR_BACKUP_ID}")
    print(restore)
```

#### Step 3: Get the restored cluster information

To get the information of the restored cluster, you can use the [Get a cluster by ID](#tag/Cluster/operation/GetCluster) endpoint.

```python
import requests
from requests.auth import HTTPDigestAuth

HOST = "https://api.tidbcloud.com"


def get_cluster_by_id(public_key: str, private_key: str, project_id: str, cluster_id: str) -> dict:
    """
    Get the cluster detail.
    You will get `connection_strings` from the response after the cluster's status is`AVAILABLE`.
    Then, you can connect to TiDB using the default user, host, and port in `connection_strings`
    :param public_key: Your public key
    :param private_key: Your private key
    :param project_id: The project id
    :param cluster_id: The cluster id
    :return: The cluster detail
    """
    url = f"{HOST}/api/v1beta/projects/{project_id}/clusters/{cluster_id}"
    resp = requests.get(url=url,
                        auth=HTTPDigestAuth(public_key, private_key))
    if resp.status_code != 200:
        print(f"request invalid, code : {resp.status_code}, message : {resp.text}")
        raise Exception(f"request invalid, code : {resp.status_code}, message : {resp.text}")
    return resp.json()


if __name__ == "__main__":
    # Replace YOUR_PUBLIC_KEY, YOUR_PRIVATE_KEY, YOUR_PROJECT_ID and YOUR_CLUSTER_ID
    cluster = get_cluster_by_id("{YOUR_PUBLIC_KEY}", "{YOUR_PRIVATE_KEY}", "{YOUR_PROJECT_ID}",
                                       "{YOUR_CLUSTER_ID}")
    print(cluster)
```

### Scale out one TiFlash node for an existing cluster

The following example shows how to scale out one TiFlash node for an existing cluster.

#### Step 1: Add one TiFlash node for the specified cluster

To add a TiFlash node for the TiDB Cloud Dedicated cluster, you can use the [Modify a TiDB Cloud Dedicated cluster](#tag/Cluster/operation/UpdateCluster) endpoint.

```python
import requests
import json
from requests.auth import HTTPDigestAuth

HOST = "https://api.tidbcloud.com"


def modify_cluster(public_key: str, private_key: str, project_id: str, cluster_id: str, tiflash_num: int) -> dict:
    """
    Add one TiFlash node for specified cluster
    If the vCPUs of TiDB or TiKV component is 4, then the cluster does not support TiFlash.
    `data_add_tiflash` below is a demo. You should fill in the field according to
    your own situation
    :param public_key: Your public key
    :param private_key: Your private key
    :param project_id: The project id
    :param cluster_id: The cluster id
    :param tiflash_num: The tiflash num
    :return: If success, return None. Else, return message
    """
    url = f"{HOST}/api/v1beta/projects/{project_id}/clusters/{cluster_id}"
    data_add_tiflash = \
        {
            "config":
                {
                    "components":
                        {
                            "tidb":
                                {
                                    "node_quantity": 1
                                },
                            "tikv":
                                {
                                    "node_quantity": 3
                                },
                            "tiflash":
                                {
                                    "node_quantity": f"{tiflash_num}",
                                    "node_size": "8C64G",
                                    "storage_size_gib": 500
                                }
                        }
                }
        }
    data_add_tiflash_json = json.dumps(data_add_tiflash)
    resp = requests.patch(url=url,
                          auth=HTTPDigestAuth(public_key, private_key),
                          data=data_add_tiflash_json)
    if resp.status_code != 200:
        print(f"request invalid, code : {resp.status_code}, message : {resp.text}")
        raise Exception(f"request invalid, code : {resp.status_code}, message : {resp.text}")
    return resp.json()


if __name__ == "__main__":
    # Replace YOUR_PUBLIC_KEY, YOUR_PRIVATE_KEY, YOUR_PROJECT_ID, YOUR_CLUSTER_ID and MODIFY_TIFLASH_NUM
    modify_cluster("{YOUR_PUBLIC_KEY}", "{YOUR_PRIVATE_KEY}", "{YOUR_PROJECT_ID}",
                   "{YOUR_CLUSTER_ID}", "{MODIFY_TIFLASH_NUM}")
```

#### Step 2: View the scale-out progress

To view the scale-out progress, you can use the [Get a cluster by ID](#tag/Cluster/operation/GetCluster) endpoint.

```python
import requests
from requests.auth import HTTPDigestAuth

HOST = "https://api.tidbcloud.com"


def get_cluster_by_id(public_key: str, private_key: str, project_id: str, cluster_id: str) -> dict:
    """
    Get the cluster detail.
    You will get `connection_strings` from the response after the cluster's status is`AVAILABLE`.
    Then, you can connect to TiDB using the default user, host, and port in `connection_strings`
    :param public_key: Your public key
    :param private_key: Your private key
    :param project_id: The project id
    :param cluster_id: The cluster id
    :return: The cluster detail
    """
    url = f"{HOST}/api/v1beta/projects/{project_id}/clusters/{cluster_id}"
    resp = requests.get(url=url,
                        auth=HTTPDigestAuth(public_key, private_key))
    if resp.status_code != 200:
        print(f"request invalid, code : {resp.status_code}, message : {resp.text}")
        raise Exception(f"request invalid, code : {resp.status_code}, message : {resp.text}")
    return resp.json()


if __name__ == "__main__":
    # Replace YOUR_PUBLIC_KEY, YOUR_PRIVATE_KEY, YOUR_PROJECT_ID and YOUR_CLUSTER_ID
    cluster = get_cluster_by_id("{YOUR_PUBLIC_KEY}", "{YOUR_PRIVATE_KEY}", "{YOUR_PROJECT_ID}",
                                       "{YOUR_CLUSTER_ID}")
    print(cluster)
```
