---
title: "One-click apps — API reference"
description: "Install a one-click app on a cloud server (the disk is rebuilt)."
url: https://www.gyrohosting.com/developers/en/api/one-click-apps.html
language: en
openapi: https://www.gyrohosting.com/developers/openapi.json
api_version: 2.30.0
---

# One-click apps

Install a one-click app on a cloud server (the disk is rebuilt).

Base URL: `https://www.gyrohosting.com/api/v1/client` · OpenAPI: https://www.gyrohosting.com/developers/openapi.json


## GET /cloud/apps

**List installable apps** · operationId `listApps` · scope `services_read` · OpenAPI fragment: https://www.gyrohosting.com/developers/spec/ops/listApps.json




### Responses

- **200**: Apps
- **401**: Missing, invalid or revoked key

### Examples

```bash
curl -s 'https://www.gyrohosting.com/api/v1/client/cloud/apps' \
  -H "Authorization: Bearer $GYRO_TOKEN"
```
```bash
gyro api request GET /cloud/apps
```
```hcl
# data source gyro_apps: https://registry.terraform.io/providers/gyro-hosting/gyro/latest/docs/data-sources/apps
# All one-click apps
data "gyro_apps" "all" {}

# Apps listed under "Popular in Türkiye" that run on Ubuntu 24.04
data "gyro_apps" "popular" {
  popular_tr = true
  os         = "ubuntu-24.04"
}

output "popular_app_ids" {
  value = [for a in data.gyro_apps.popular.apps : a.id]
}
```
```python
import os, uuid, requests

h = {"Authorization": "Bearer " + os.environ["GYRO_TOKEN"]}
r = requests.get("https://www.gyrohosting.com/api/v1/client/cloud/apps", headers=h, timeout=60)
r.raise_for_status()
print(r.json()["data"])
```
```js
const res = await fetch("https://www.gyrohosting.com/api/v1/client/cloud/apps", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${process.env.GYRO_TOKEN}`,
  },
});
const { data, error } = await res.json();
if (!res.ok) throw new Error(`${error.code}: ${error.message}`);
```


## GET /cloud/servers/{id}/app

**App install status (credentials shown once when ready)** · operationId `getAppInstall` · scope `cloud_read` · OpenAPI fragment: https://www.gyrohosting.com/developers/spec/ops/getAppInstall.json

Since 2.7.0 also `stuck` (open but silent for too long), `stuck_reason` (`no_callback` = the server never reported back), `last_update_at`, `attempt`, `can_retry`, `error_code`, `step_text`. Live log: GET /cloud/servers/{id}/app/log.


### Parameters

| Field | in | Type | Description |
|---|---|---|---|
| `id` (required) | path | integer | Server id (= service id in the client area) |

### Responses

- **200**: Status
- **404**: Not found — also returned for objects owned by someone else

### Examples

```bash
curl -s 'https://www.gyrohosting.com/api/v1/client/cloud/servers/12345/app' \
  -H "Authorization: Bearer $GYRO_TOKEN"
```
```bash
gyro server app get 12345
```
```hcl
# resource gyro_app_install: https://registry.terraform.io/providers/gyro-hosting/gyro/latest/docs/resources/app_install
# WARNING: installing an app rebuilds the server disk
resource "gyro_app_install" "wp" {
  server_id = tonumber(gyro_server.web.id)
  app       = "wordpress"
  domain    = "blog.example.com"
  email     = "admin@example.com"
}
```
```python
import os, uuid, requests

h = {"Authorization": "Bearer " + os.environ["GYRO_TOKEN"]}
r = requests.get("https://www.gyrohosting.com/api/v1/client/cloud/servers/12345/app", headers=h, timeout=60)
r.raise_for_status()
print(r.json()["data"])
```
```js
const res = await fetch("https://www.gyrohosting.com/api/v1/client/cloud/servers/12345/app", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${process.env.GYRO_TOKEN}`,
  },
});
const { data, error } = await res.json();
if (!res.ok) throw new Error(`${error.code}: ${error.message}`);
```


## POST /cloud/servers/{id}/app

**Install an app (rebuilds the disk; confirm required; 3 per server per day)** · operationId `installApp` · scope `cloud_write` · OpenAPI fragment: https://www.gyrohosting.com/developers/spec/ops/installApp.json



**2.19.1**: also on tr-ist-1 (Gyro Cloud Istanbul) servers. Equivalent to `POST /cloud/servers/{id}/actions/rebuild` with `app`.


### Parameters

| Field | in | Type | Description |
|---|---|---|---|
| `id` (required) | path | integer | Server id (= service id in the client area) |

### Request body

| Field | Type | Description |
|---|---|---|
| `app` (required) | string |  |
| `os` | string |  |
| `domain` | string |  |
| `email` | string |  |
| `confirm` (required) | boolean = true |  |

### Responses

- **202**: Started
- **404**: Not found — also returned for objects owned by someone else
- **409**: State conflict (`server_locked`, `not_actionable`, `ssh_key_exists`, `server_limit`, `idempotency_in_flight`)
- **422**: Validation or business rule failure (`confirm_required`, `invalid_image`, `tool_action_failed` ...)
- **429**: install_limit

### Examples

```bash
curl -s -X POST 'https://www.gyrohosting.com/api/v1/client/cloud/servers/12345/app' \
  -H "Authorization: Bearer $GYRO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"app": "wordpress", "domain": "blog.example.com", "email": "admin@example.com", "confirm": true}'
```
```bash
gyro server app create 12345 --help    # all flags
```
```hcl
# resource gyro_app_install: https://registry.terraform.io/providers/gyro-hosting/gyro/latest/docs/resources/app_install
# WARNING: installing an app rebuilds the server disk
resource "gyro_app_install" "wp" {
  server_id = tonumber(gyro_server.web.id)
  app       = "wordpress"
  domain    = "blog.example.com"
  email     = "admin@example.com"
}
```
```python
import os, uuid, requests

h = {"Authorization": "Bearer " + os.environ["GYRO_TOKEN"]}
r = requests.post("https://www.gyrohosting.com/api/v1/client/cloud/servers/12345/app", headers=h, json={"app": "wordpress", "domain": "blog.example.com", "email": "admin@example.com", "confirm": True}, timeout=60)
r.raise_for_status()
print(r.json()["data"])
```
```js
const res = await fetch("https://www.gyrohosting.com/api/v1/client/cloud/servers/12345/app", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.GYRO_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"app": "wordpress", "domain": "blog.example.com", "email": "admin@example.com", "confirm": true}),
});
const { data, error } = await res.json();
if (!res.ok) throw new Error(`${error.code}: ${error.message}`);
```


## GET /cloud/servers/{id}/app/log

**Live progress log of the latest app install (step changes, server log tail)** · operationId `getAppInstallLog` · scope `cloud_read` · OpenAPI fragment: https://www.gyrohosting.com/developers/spec/ops/getAppInstallLog.json

Lines with `id` greater than `after`, oldest first (poll with the last id you have). `source` is step, server, system or staff. Server lines are untrusted text sent by the server (secrets masked); render them as plain text.


### Parameters

| Field | in | Type | Description |
|---|---|---|---|
| `id` (required) | path | integer | Server id (= service id in the client area) |
| `after` | query | integer |  |
| `limit` | query | integer |  |

### Responses

- **200**: Log lines
- **404**: Not found — also returned for objects owned by someone else

### Examples

```bash
curl -s 'https://www.gyrohosting.com/api/v1/client/cloud/servers/12345/app/log' \
  -H "Authorization: Bearer $GYRO_TOKEN"
```
```bash
gyro server app log get 12345
```
```python
import os, uuid, requests

h = {"Authorization": "Bearer " + os.environ["GYRO_TOKEN"]}
r = requests.get("https://www.gyrohosting.com/api/v1/client/cloud/servers/12345/app/log", headers=h, timeout=60)
r.raise_for_status()
print(r.json()["data"])
```
```js
const res = await fetch("https://www.gyrohosting.com/api/v1/client/cloud/servers/12345/app/log", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${process.env.GYRO_TOKEN}`,
  },
});
const { data, error } = await res.json();
if (!res.ok) throw new Error(`${error.code}: ${error.message}`);
```


## POST /cloud/servers/{id}/app/retry

**Retry a failed or silent app install (rebuilds the disk; confirm required; 3 per server per hour)** · operationId `retryAppInstall` · scope `cloud_write` · OpenAPI fragment: https://www.gyrohosting.com/developers/spec/ops/retryAppInstall.json

Allowed when the latest install has `status` hata (failed) or `stuck` = true (no news for too long). On cloud servers the server is rebuilt with the same app, OS and domain; ALL data on the disk is deleted.


### Parameters

| Field | in | Type | Description |
|---|---|---|---|
| `id` (required) | path | integer | Server id (= service id in the client area) |

### Request body

| Field | Type | Description |
|---|---|---|
| `confirm` (required) | boolean = true |  |

### Responses

- **202**: Started (install_id, attempt)
- **404**: Not found — also returned for objects owned by someone else
- **409**: State conflict (`server_locked`, `not_actionable`, `ssh_key_exists`, `server_limit`, `idempotency_in_flight`)
- **422**: Validation or business rule failure (`confirm_required`, `invalid_image`, `tool_action_failed` ...)
- **429**: install_limit

### Examples

```bash
curl -s -X POST 'https://www.gyrohosting.com/api/v1/client/cloud/servers/12345/app/retry' \
  -H "Authorization: Bearer $GYRO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"confirm": true}'
```
```bash
gyro server app retry 12345 --help    # all flags
```
```python
import os, uuid, requests

h = {"Authorization": "Bearer " + os.environ["GYRO_TOKEN"]}
r = requests.post("https://www.gyrohosting.com/api/v1/client/cloud/servers/12345/app/retry", headers=h, json={"confirm": True}, timeout=60)
r.raise_for_status()
print(r.json()["data"])
```
```js
const res = await fetch("https://www.gyrohosting.com/api/v1/client/cloud/servers/12345/app/retry", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.GYRO_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"confirm": true}),
});
const { data, error } = await res.json();
if (!res.ok) throw new Error(`${error.code}: ${error.message}`);
```
