---
title: "Tihost API: automate buying and managing VPS servers"
description: "The Tihost public API: get a key in the panel or bot, buy a server with POST /servers, reboot, renew, 60/10 per-minute limits, curl and Python examples."
url: https://tihost.io/en/blog/tihost-api-automation
language: en
section: "Platform"
published: 2026-10-05
updated: 2026-10-05
publisher: Tihost (https://tihost.io)
---

# Tihost API: automate buying and managing VPS servers

> **In short:** The Tihost API is an HTTP JSON API at https://api-public.tihost.io/v1: the key is issued in the panel's «API» section or in the bot and sent in the Authorization: Bearer header. The API can buy a server (POST /servers), renew it, reboot it, reinstall the OS and reset the password; the limit is 60 read and 10 write requests per minute per key.

**Key takeaways:**

- The Tihost public API lives at https://api-public.tihost.io/v1, accepts and returns JSON, and takes the access key in the `Authorization: Bearer <key>` header.
- A Tihost API key is issued in the web panel's «API» section with «Issue key» or in the Telegram bot under «Profile» - «API key»; its value is shown only once.
- The Tihost API limit is per key: 60 requests per minute for reads and 10 per minute for methods that change servers or spend money; going over returns 429 with a Retry-After header.
- Buying (POST /servers) and renewing (POST /servers/{id}/renew) through the Tihost API charge the balance, so they are sent with an Idempotency-Key header - a retry with the same key never buys a second server.

Every method, response field and error code is described on the [API documentation](https://tihost.io/api) page. This guide is the fast path from a key to a purchased and rebooted server.

## What you can do with the Tihost API

| Method | Path | What it does |
| --- | --- | --- |
| GET | `/ping` | Checks the key, returns the account id and server time |
| GET | `/balance` | Account balance in US dollars |
| GET | `/catalog/plans?location=…` | Configurations in a location with prices for 1, 3, 6 and 12 months |
| GET | `/catalog/os?location=…&plan_id=…` | OS images for the chosen configuration |
| POST | `/servers` | Buys a server - charges the balance |
| GET | `/servers` | Lists the account's servers |
| GET | `/servers/{id}` | One server: IP, state, resources, renewal prices |
| POST | `/servers/{id}/renew` | Renews for 2, 7, 30, 90, 180 or 365 days - charges the balance |
| PATCH | `/servers/{id}/auto-renew` | Turns auto-renewal on or off |
| POST | `/servers/{id}/power` | Start, stop, reboot |
| PATCH | `/servers/{id}/name` | Renames the server |
| POST | `/servers/{id}/password` | Resets the root or Administrator password |
| GET | `/servers/{id}/os` | Images that can be installed on the server |
| POST | `/servers/{id}/reinstall` | Reinstalls the OS - wipes the disk |
| GET | `/servers/{id}/scripts` | Scripts available for the server's OS |
| POST | `/servers/{id}/scripts/run` | Runs a script on the server |

*Paths are relative to the base https://api-public.tihost.io/v1. Topping up the balance and changing the IP address are not available in the API - use the panel or the bot.*

## Step 1. Issue an API key

In the [panel](https://tihost.io/login) open the «API» section and press «Issue key»; in the @tihost_bot bot it is «Profile» - «API key». The key starts with `tih_`, never expires and is shown only once: the server stores only its hash, so save it to a password manager or an environment variable right away. An account has one key; «Reissue» disables the old one instantly.

> The key gives access to the whole account, including purchases from the balance. Never put it in client-side code, public repositories or chats - keep it in an environment variable or CI secrets.

## Step 2. Check the key with /ping

Put the key and the base URL into environment variables and call `/ping` - it changes nothing and only confirms that the key works. Replace `YOUR_API_KEY` with your key:

```bash
export TIHOST_TOKEN="YOUR_API_KEY"
export TIHOST_API="https://api-public.tihost.io/v1"

curl -H "Authorization: Bearer $TIHOST_TOKEN" "$TIHOST_API/ping"
```

`Response`:

```
{
  "status": "ok",
  "account_id": 1042,
  "server_time": "2026-10-05T12:30:00Z"
}
```

## Step 3. Check the balance, plans and OS images

A purchase needs two ids: the configuration's `plan_id` from `/catalog/plans` and the image's `os_id` from `/catalog/os`. The numbers 41 and 101 in the examples are placeholders - take them from the catalog response, not from this article. The location code is `germany`, `finland` or `poland`:

```bash
curl -H "Authorization: Bearer $TIHOST_TOKEN" "$TIHOST_API/balance"
curl -H "Authorization: Bearer $TIHOST_TOKEN" "$TIHOST_API/catalog/plans?location=germany"
curl -H "Authorization: Bearer $TIHOST_TOKEN" "$TIHOST_API/catalog/os?location=germany&plan_id=41"
```

For each configuration the catalog returns `cpu`, `ram_mb`, `disk_gb` and a `periods` array with the total for 1, 3, 6 and 12 months - the 10, 15 and 20% discounts are already applied.

## Step 4. Buy a server

A purchase is `POST /servers` with the location, `plan_id`, `os_id` and the term in `months` (1, 3, 6 or 12); the optional `name` field sets the server name. The price is charged to the balance, so generate the `Idempotency-Key` once and send the same key when retrying after a timeout - the API returns the stored response and does not create a second machine:

```bash
IDEMPOTENCY_KEY=$(uuidgen)   # on Linux without uuidgen: cat /proc/sys/kernel/random/uuid

curl -X POST "$TIHOST_API/servers" \
  -H "Authorization: Bearer $TIHOST_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -d '{"location": "germany", "plan_id": 41, "os_id": 101, "months": 1}'
```

`Response 201`:

```
{
  "id": 2427,
  "name": "my-server-1",
  "os": "Ubuntu 24.04",
  "location": "germany",
  "login": "root",
  "password": "********",
  "rent_expires_at": "2026-11-04T10:00:00Z",
  "charged_usd": "4.00",
  "balance_usd": "6.00"
}
```

The response already contains `login` and `password`, but no IP address yet: the machine takes about 2 minutes to deploy. Read the IP and state with `GET /servers/{id}`. If the balance is short, you get a 402 `insufficient_funds` error with the missing amount in `details.missing_usd`.

## Step 5. Manage servers: list, reboot, renew

Read methods (`GET`) are safe to call in a loop, and write methods (`POST` and `PATCH`) accept the same `Idempotency-Key` header. The panel runs power commands asynchronously: the `power` response tells which state the machine is moving to (`running`, `stopped` or `restarting`), and the actual state shows in `GET /servers/{id}`:

```bash
# all servers on the account
curl -H "Authorization: Bearer $TIHOST_TOKEN" "$TIHOST_API/servers"

# one server: IP, state, resources, renewal prices
curl -H "Authorization: Bearer $TIHOST_TOKEN" "$TIHOST_API/servers/2427"

# reboot (action: start, stop or restart)
curl -X POST "$TIHOST_API/servers/2427/power" \
  -H "Authorization: Bearer $TIHOST_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"action": "restart"}'

# renew for 30 days from the balance
curl -X POST "$TIHOST_API/servers/2427/renew" \
  -H "Authorization: Bearer $TIHOST_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"days": 30}'
```

## Python example: buy a server and wait for its IP

This script uses the `requests` library (`pip install requests`) to pick the 1 vCPU / 2 GB configuration in Germany, buy it for a month with Ubuntu and wait for the IP address. The key comes from the `TIHOST_TOKEN` environment variable, and a 429 response is handled by sleeping for `Retry-After` seconds:

`buy_server.py`:

```python
import os
import time
import uuid

import requests

BASE = "https://api-public.tihost.io/v1"
TOKEN = os.environ["TIHOST_TOKEN"]  # YOUR_API_KEY - from the environment, not from code


def api(method, path, body=None, idempotency_key=None):
    headers = {"Authorization": f"Bearer {TOKEN}"}
    if idempotency_key:
        headers["Idempotency-Key"] = idempotency_key
    while True:
        r = requests.request(method, BASE + path, headers=headers, json=body, timeout=30)
        if r.status_code == 429:  # rate limit: wait as long as the server says
            time.sleep(int(r.headers.get("Retry-After", "5")))
            continue
        if not r.ok:
            err = r.json()["error"]
            raise RuntimeError(f"{err['code']}: {err['message']} (request_id={err['request_id']})")
        return r.json()


# 1. The 1 vCPU / 2 GB configuration in Germany and Ubuntu for it
plans = api("GET", "/catalog/plans?location=germany")["items"]
plan = next(p for p in plans if p["cpu"] == 1 and p["ram_mb"] == 2048)
images = api("GET", f"/catalog/os?location=germany&plan_id={plan['id']}")["items"]
os_id = next(i["id"] for i in images if i["name"].startswith("Ubuntu"))

# 2. Buy for one month. One idempotency key per purchase: a retry never buys a second server
order = api(
    "POST",
    "/servers",
    body={"location": "germany", "plan_id": plan["id"], "os_id": os_id, "months": 1},
    idempotency_key=str(uuid.uuid4()),
)
print("login:", order["login"], "password:", order["password"])

# 3. Wait for the IP address (up to 10 minutes, polling every 15 seconds)
for _ in range(40):
    server = api("GET", f"/servers/{order['id']}")
    if server["ip"]:
        print("ip:", server["ip"], "state:", server["state"])
        break
    time.sleep(15)
```

## Tihost API errors and limits

Every error comes in one format - an `error` object with `code`, `message`, `request_id` and sometimes `details`. Branch on `code`: it is stable, while the `message` text may change.

`Response 429`:

```
{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded: 60 read requests per 60 seconds",
    "details": { "limit": 60, "scope": "read", "retry_after": 27 },
    "request_id": "9f4c1d0e8b7a4c2f9e1d3b6a8c5f2e7d"
  }
}
```

| HTTP | code | Meaning |
| --- | --- | --- |
| 400 | `invalid_request` | The request failed validation, reasons in `details.fields` |
| 401 | `unauthorized`, `token_invalid` | No Authorization header, or the key was revoked |
| 402 | `insufficient_funds` | Not enough money on the balance |
| 404 | `not_found` | The server does not exist or belongs to another account |
| 409 | `server_busy`, `rent_expired`, `conflict` | The machine is busy with another operation, the rental expired, or the action is impossible in the current state |
| 422 | `idempotency_key_reused` | The same Idempotency-Key was sent with a different request |
| 429 | `rate_limited` | Rate limit exceeded - retry after Retry-After seconds |

*The full list of codes is on the API documentation page.*

- The limit is 60 requests per minute for reads and 10 per minute for writes, per key; the windows are independent, so a stream of reads never blocks management.
- Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` headers, so a script can slow down before it is refused.
- The idempotency key (`Idempotency-Key`) is a string of up to 128 characters, usually a UUID; it lives for 24 hours, and a replayed response is marked with `Idempotent-Replay: true`.
- The API version is in the path (`/v1`): within it fields may be added but are never renamed or removed.
- If a response looks wrong, write to tech-support@tihost.io with the `request_id` - it identifies the exact call.

> The old base https://tihost.io/api/public/v1 is deprecated and will be switched off soon. Use https://api-public.tihost.io/v1 - the current address is always shown on the [API documentation](https://tihost.io/api) page and in the panel's «API» section.

**Launch a server in 2 minutes.** AMD Ryzen 9, NVMe and DDoS protection in Germany, Finland and Poland. Pay with crypto or card. [Order a Server](https://tihost.io/login)

## FAQ

### Where do I get a Tihost API key?

In the tihost.io web panel: the «API» section, «Issue key» button. In the Telegram bot @tihost_bot the key is issued under «Profile» - «API key». The value is shown once; after that it can only be reissued.

### Can I buy a VPS through the Tihost API?

Yes, with POST /servers and the fields location, plan_id, os_id and months; the price is charged to the account balance. The configuration and image ids come from GET /catalog/plans and GET /catalog/os.

### How do I reboot a server through the Tihost API?

Send POST /servers/{id}/power with the body {"action": "restart"} and an Authorization: Bearer header. The values start and stop power the server on and off.

### What are the Tihost API rate limits?

60 requests per minute for reads and 10 per minute for methods that change servers or spend money, counted per key. Going over returns 429 with the code rate_limited and a Retry-After header.

### What happens if I retry a purchase request after a timeout?

If the retry carries the same Idempotency-Key header, the Tihost API returns the stored response of the first purchase and does not create a second server. Without that header, the retry buys another machine.

### Can I top up the balance or change the IP through the Tihost API?

No. Balance top-ups and IP changes are available only in the web panel and the Telegram bot; the API works with a balance that is already funded.

---

Updated 2026-10-05 · https://tihost.io/en/blog/tihost-api-automation
