{
 "openapi": "3.1.0",
 "info": {
  "title": "Gyro Public API",
  "version": "2.30.0",
  "summary": "Manage Gyro cloud servers, SSH keys and billing programmatically.",
  "x-summary-tr": "Gyro bulut sunucularınızı, SSH anahtarlarınızı ve faturalarınızı programla yönetin.",
  "contact": {
   "name": "Gyro Hosting",
   "url": "https://www.gyrohosting.com"
  },
  "license": {
   "name": "Proprietary",
   "identifier": "LicenseRef-Gyro-API-Terms"
  }
 },
 "servers": [
  {
   "url": "https://www.gyrohosting.com/api/v1/client",
   "description": "Production"
  }
 ],
 "paths": {
  "/cloud/containers/{id}/services": {
   "post": {
    "tags": [
     "Containers"
    ],
    "operationId": "typed_post_containers__id__services",
    "summary": "Create a container service",
    "x-summary-tr": "Kapsayıcı servisi oluştur",
    "x-scope": "services_write",
    "description": "Starts a new service on your dedicated node pool. Name: lowercase letters, digits and '-', max 40. Fails with 409 `quota_exceeded` when the pool has no room. Secret values are set separately (PUT .../secrets). **Serverless environments:** `cpu_m` / `memory_mi` must be one of the pairs from `GET /cloud/billing/container-sizes` (0.25-4 vCPU); billing is per running copy per hour (`POST /cloud/billing/estimate` with `type: serverless`). Refused with 422 `invalid_replicas` (`details.max` = your plan's limit) when the count is outside 0..max copies per service. `alerts` takes one field, `min_ready` (0 = off); `autoscaling` takes enabled, min, max, cpu_percent, memory_percent. Any other field inside them is refused with 422 `invalid_alerts` / `invalid_autoscaling` (it used to be dropped silently).",
    "x-description-tr": "Size ayrılmış düğüm havuzunda yeni servis başlatır. Ad: küçük harf, rakam, '-', en çok 40. Havuzda yer yoksa 409 `quota_exceeded`. Gizli değerler ayrıca (PUT .../secrets). **Sunucusuz ortam:** `cpu_m` / `memory_mi` `GET /cloud/billing/container-sizes` çiftlerinden biri olmalı (0,25-4 vCPU); ücret çalışan kopya başına saatliktir (`POST /cloud/billing/estimate`, `type: serverless`). Sayı servis başına 0..en fazla kopya aralığı dışındaysa 422 `invalid_replicas` (`details.max` = planınızın sınırı). `alerts` tek alan alır, `min_ready` (0 = kapalı); `autoscaling` enabled, min, max, cpu_percent, memory_percent alır. İçlerindeki başka alan 422 `invalid_alerts` / `invalid_autoscaling` ile reddedilir (eskiden sessizce düşüyordu).",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      },
      "description": "Service id"
     }
    ],
    "responses": {
     "202": {
      "description": "Tool data / result",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "data": {
           "type": "object",
           "additionalProperties": true
          }
         }
        }
       }
      }
     },
     "404": {
      "$ref": "#/components/responses/NotFound"
     },
     "409": {
      "$ref": "#/components/responses/Conflict"
     },
     "422": {
      "$ref": "#/components/responses/Validation"
     }
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string",
          "description": "Service name",
          "x-description-tr": "Servis adı"
         },
         "image": {
          "type": "string",
          "description": "Image reference, e.g. ghcr.io/acme/web:1.4 (public registries or your private registry)",
          "x-description-tr": "İmaj, ör. ghcr.io/firma/web:1.4"
         },
         "port": {
          "type": "integer",
          "description": "Container port (0 = no network port). Containers run as a non-root user: use a port >= 1024",
          "x-description-tr": "Kapsayıcı portu (0 = port yok). Kök olmayan kullanıcı: 1024 üstü port"
         },
         "replicas": {
          "type": "integer",
          "description": "Number of instances (default 1)",
          "x-description-tr": "Örnek sayısı (varsayılan 1)"
         },
         "cpu_m": {
          "type": "integer",
          "description": "CPU per instance in millicores (250 = 0.25 vCPU)",
          "x-description-tr": "Örnek başına işlemci (milicore, 250 = 0,25 vCPU)"
         },
         "memory_mi": {
          "type": "integer",
          "description": "Memory per instance in MiB",
          "x-description-tr": "Örnek başına bellek (MiB)"
         },
         "public": {
          "type": "boolean",
          "description": "HTTPS address <name>-<code>.gyroapp.net (and your domains)",
          "x-description-tr": "HTTPS adres <ad>-<kod>.gyroapp.net"
         },
         "health_path": {
          "type": "string",
          "description": "HTTP health check path (empty = TCP check)",
          "x-description-tr": "HTTP sağlık yolu (boş = TCP)"
         },
         "args": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "description": "Arguments for the image's default command. A JSON array of strings, e.g. [\"sh\",\"-c\",\"echo a && npm start\"]. A plain string is accepted too and split like a shell: whitespace separates, quotes keep text together (\"...\" with \\\" escapes, '...' literal): `sh -c \"echo a && npm start\"` -> [\"sh\",\"-c\",\"echo a && npm start\"]. A string starting with [ must be a valid JSON array; an unclosed quote is an error.",
          "x-description-tr": "İmajın komutuna argümanlar. JSON metin dizisi, ör. [\"sh\",\"-c\",\"echo a && npm start\"]. Düz metin de olur, kabuk gibi bölünür: boşluk ayırır, tırnak birleştirir (\"...\" içinde \\\" kaçışı, '...' olduğu gibi): `sh -c \"echo a && npm start\"`. [ ile başlayan metin geçerli JSON dizi olmalı; kapanmamış tırnak hata verir."
         },
         "command": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "description": "Override the image entrypoint. A JSON array of strings, e.g. [\"sh\",\"-c\",\"echo a && npm start\"]. A plain string is accepted too and split like a shell: whitespace separates, quotes keep text together (\"...\" with \\\" escapes, '...' literal): `sh -c \"echo a && npm start\"` -> [\"sh\",\"-c\",\"echo a && npm start\"]. A string starting with [ must be a valid JSON array; an unclosed quote is an error.",
          "x-description-tr": "İmajın giriş komutunu değiştir. JSON metin dizisi, ör. [\"sh\",\"-c\",\"echo a && npm start\"]. Düz metin de olur, kabuk gibi bölünür: boşluk ayırır, tırnak birleştirir (\"...\" içinde \\\" kaçışı, '...' olduğu gibi): `sh -c \"echo a && npm start\"`. [ ile başlayan metin geçerli JSON dizi olmalı; kapanmamış tırnak hata verir."
         },
         "env": {
          "type": "object",
          "additionalProperties": {
           "type": "string"
          },
          "description": "Plain environment variables (replaces the whole set on update)",
          "x-description-tr": "Ortam değişkenleri (güncellemede tamamı değişir)"
         },
         "run_as_user": {
          "type": "integer",
          "description": "User id inside the container (default 10001)",
          "x-description-tr": "Kapsayıcı içi kullanıcı kimliği (varsayılan 10001)"
         },
         "autoscaling": {
          "type": "object",
          "description": "Autoscaling (horizontal): replicas follow the average CPU (and optionally memory) use of the reserved size. `enabled:false` = off (fixed replicas).",
          "x-description-tr": "Otomatik ölçekleme: kopya sayısı ayrılan boyutun ortalama CPU (isteğe bağlı bellek) kullanımına göre değişir. `enabled:false` = kapalı.",
          "properties": {
           "enabled": {
            "type": "boolean"
           },
           "min": {
            "type": "integer",
            "minimum": 1
           },
           "max": {
            "type": "integer",
            "description": "<= plan replica limit"
           },
           "cpu_percent": {
            "type": "integer",
            "minimum": 10,
            "maximum": 95,
            "default": 70
           },
           "memory_percent": {
            "type": "integer",
            "description": "0 = off, else 10-95"
           }
          }
         },
         "alerts": {
          "type": "object",
          "description": "Alert threshold: notify when fewer replicas are ready (0 = off). Channels: PUT /cloud/containers/{id}/notifications.",
          "x-description-tr": "Uyarı eşiği: hazır kopya bu sayının altına düşerse bildirim (0 = kapalı).",
          "properties": {
           "min_ready": {
            "type": "integer"
           }
          }
         },
         "confirm": {
          "type": "boolean"
         }
        },
        "required": [
         "name",
         "image"
        ]
       }
      }
     }
    },
    "x-cli": {
     "command": "container service create",
     "confirm": false
    }
   }
  }
 },
 "components": {
  "responses": {
   "Validation": {
    "description": "Validation or business rule failure (`confirm_required`, `invalid_image`, `tool_action_failed` ...)",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      }
     }
    }
   },
   "Conflict": {
    "description": "State conflict (`server_locked`, `not_actionable`, `ssh_key_exists`, `server_limit`, `idempotency_in_flight`)",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      }
     }
    }
   },
   "NotFound": {
    "description": "Not found — also returned for objects owned by someone else",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      }
     }
    }
   }
  },
  "schemas": {
   "Error": {
    "type": "object",
    "required": [
     "error"
    ],
    "properties": {
     "error": {
      "type": "object",
      "required": [
       "code",
       "message"
      ],
      "properties": {
       "code": {
        "type": "string",
        "example": "server_not_found"
       },
       "message": {
        "type": "string"
       },
       "details": {
        "type": "object",
        "additionalProperties": true,
        "description": "Extra data. Limit refusals add the LimitHint fields (`limit_exceeded: true`, `limit_key`, `limit`, `current`, `how_to_increase`, `support_ticket`, `hint`): account limits are raised with a support ticket. Validation errors (length, format) never carry the limit hint.",
        "x-description-tr": "Ek veri. Sınır retlerinde LimitHint alanları gelir: hesap sınırları destek talebiyle artırılır. Doğrulama hataları (uzunluk, biçim) sınır ipucu taşımaz."
       }
      }
     }
    }
   }
  }
 },
 "security": [
  {
   "bearerAuth": []
  }
 ]
}